2015-04-10 1 views
4

У меня есть требование в Oracle, где я должен передать цепочку разделенных запятыми строк кодов в хранимую процедуру Oracle.Сплит-строка и итерация для каждого значения в хранимой процедуре

Внутри хранимой процедуры я хочу разбить строку на запятую и выполнить итерацию для каждого кода страны.

Я хочу SP, который похож следующим образом:

PROCEDURE Get_Query 
(
    v_company IN VARCHAR2, 

) IS 
sqlstr VARCHAR2(32767); 
BEGIN 
/* 
split the v_company on comma (e.g. IN,US,...etc) 
iterate for each country code 

*/ 
END; 
+0

Это такой распространенный запрос (попробуйте Googling, "stackoverflow oracle parse csv string"). Нет недостатка в документации по этому вопросу. –

ответ

7

Вы можете использовать DBMS_UTILITY.COMMA_TO_TABLE.

DBMS_UTILITY пакет предоставляет различные подпрограммы утилиты. Одна такая полезная утилита: COMMA_TO_TABLE процедура, которая преобразует список имен с разделителями-запятыми в таблицу имен PL/SQL.

Например,

SQL> set serveroutput on; 
SQL> DECLARE 
    2 l_tablen BINARY_INTEGER; 
    3 l_tab DBMS_UTILITY.uncl_array; 
    4 CURSOR cur 
    5 IS 
    6  SELECT 'word1, word2, word3, word4, word5, word6' val FROM dual; 
    7 rec cur%rowtype; 
    8 BEGIN 
    9 OPEN cur; 
10 LOOP 
11  FETCH cur INTO rec; 
12  EXIT 
13 WHEN cur%notfound; 
14  DBMS_UTILITY.comma_to_table (
15  list => rec.val, tablen => l_tablen, tab => l_tab); 
16  FOR i IN 1 .. l_tablen 
17  LOOP 
18  DBMS_OUTPUT.put_line(i || ' : ' || trim(l_tab(i))); 
19  END LOOP; 
20 END LOOP; 
21 CLOSE cur; 
22 END; 
23/
1 : word1 
2 : word2 
3 : word3 
4 : word4 
5 : word5 
6 : word6 

PL/SQL procedure successfully completed. 

SQL> 

UPDATE Как @ruudvan указывает, существуют ограничения для использования COMMA_TO_TABLE подобного не будет работать, если у вас есть ключевые слова как строку с разделителями как IS,AS и т.д.

Чтобы преодолеть ограничения COMMA_TO_TABLE, есть много других способов сделать это, см. How to split comma delimited string into rows in Oracle

Например, вы можете использовать регулярные выражения, как показано ниже:

испытания случае

SQL> CREATE OR REPLACE 
    2 PROCEDURE Get_Query(
    3  v_company IN VARCHAR2) 
    4 IS 
    5 BEGIN 
    6  
    7 FOR i IN 
    8 (SELECT level, 
    9  trim(regexp_substr(v_company, '[^,]+', 1, LEVEL)) str 
10 FROM dual 
11  CONNECT BY regexp_substr(v_company , '[^,]+', 1, LEVEL) IS NOT NULL 
12 ) 
13 LOOP 
14  -- do something 
15  dbms_output.put_line('Company code no.'||i.level||' = '||i.str); 
16 END LOOP; 
17 END; 
18/

Procedure created. 

SQL> sho err 
No errors. 

Давайте проверим:

SQL> set serveroutput on 
SQL> EXEC get_query('COMP1,COMP2,COMP3,COMP4'); 
Company code no.1 = COMP1 
Company code no.2 = COMP2 
Company code no.3 = COMP3 
Company code no.4 = COMP4 

PL/SQL procedure successfully completed. 

SQL> 
+0

Я думаю, вам стоит вместо этого использовать метод regexp_substr вместо comma_to_table. Всякий раз, когда вы рекомендуете кому-то comma_to_table, я чувствую, что вы также должны сообщить им о своих ограничениях. Том Ките подводит итог [здесь] (https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1415803954123). Это может не дать вам правильных результатов даже в этом конкретном примере кодов стран, потому что OP может иметь коды стран, такие как «AS» и «IS», которые являются зарезервированными словами, а comma_to_table не сможет их обработать. – ruudvan

+0

@ruudvan Конечно, есть ограничения со встроенным пакетом. Именно по этой причине я предоставил ссылку на мою статью, где я продемонстрировал различные методы. Я оставлю его до OP, чтобы вернуться и спросить, нужна ли ему дополнительная помощь. Если мне нужно углубиться в детали и предоставить здесь все микро-детали, то это будет похоже на книгу. В любом случае, спасибо за комментарий. Я буду более чем счастлив помочь OP, если он вернется с дальнейшими проблемами. –

+0

У вас достаточно репутации, чтобы узнать, как работает StackOverflow. Мы должны предоставить рабочие ответы * на этом сайте *. Предлагая решение подпараллеля, и, как указывает @ruudvan, 'COMMA_TO_TABLE()' это просто - плюс ссылка на ваш блог просто не достаточно хороша. – APC

1

Это использование регулярных выражений преобразует входную строку в поток токенов, который может обрабатываться как результирующий набор любой другой инструкции SELECT.

PROCEDURE Get_Query 
(
    v_company IN VARCHAR2, 

) IS 
    sqlstr VARCHAR2(32767); 
BEGIN 

    for rec in (select distinct regexp_substr(v_company, '[^,]+', 1, level) as ctry 
    from dual 
    connect by level <= regexp_count (v_company, '[,]') +1 
    loop 
     do_something (rec.ctry); 

    end loop; 
END; 
Смежные вопросы