2016-07-15 8 views
0

У меня есть образец объекта CLOB, как показано ниже. Я хочу сначала разделить это, используя разделитель «,» и сохранить его во временной таблице для последующего использования.Как разбить объект CLOB с использованием и: разделитель в Oracle на несколько записей

ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0 

Я хочу сохранить результат в нижнем формате в каждой строке.

Column_Name 
__________________________ 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 

Я попытался с помощью функции REGEXP_SUBSTR

select 
    regexp_substr('ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0', '[^,]+', 1, 1) Column_Name 
from dual; 

приведенных выше запроса дает мне одну запись, как показано ниже

Column_Name 
__________________________ 
ABCDEF:PmId12345RmLn1VlId0 

Может кто-нибудь помочь мне решить эту проблему.

ответ

2

Вот решение, используя рекурсивную разложенном подзапрос (Oracle 11.2 и выше):

with inputs (str) as (
     select to_clob('ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0') 
     from dual 
    ), 
    prep (s, n, token, st_pos, end_pos) as (
     select ',' || str || ',', -1, null, null, 1 
     from inputs 
     union all 
     select s, n+1, substr(s, st_pos, end_pos - st_pos), 
       end_pos + 1, instr(s, ',', 1, n+3) 
     from prep 
     where end_pos != 0 
    ) 
select n as idx, token as column_name 
from prep 
where n > 0; 



    IDX COLUMN_NAME 
------ ---------------------------- 
    1 ABCDEF:PmId12345RmLn1VlId0 
    2 ABCDEF:PmId12345RmLn1VlId0 
    3 ABCDEF:PmId12345RmLn1VlId0 
    4 ABCDEF:PmId12345RmLn1VlId0 
    5 ABCDEF:PmId12345RmLn1VlId0 

Примечания:

Вы сказали CLOB, но в вашем примере вы извлекли из строки varchar2. Я добавил to_clob(), чтобы узнать, работает ли это на CLOB.

Я использовал instr и substr, так как они часто (обычно?) Выполняют между лучшими и намного лучшими, чем их эквиваленты regexp.

Я сохранил «индекс» каждой подстроки во входной строке; в некоторых случаях важен порядок токенов во входной строке. (Не в вашем примере, хотя, вы только что тот же маркер повторяется пять раз.)

Если вам нужна более высокую производительность, особенно если CLOBs очень большой, вы можете быть лучше использовать dbms_lob.substr и dbms_lob.instr - см Performance of SUBSTR on CLOB, особенно Ответ Алексея Пула и документация здесь: http://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_lob.htm#BABEAJAD. Обратите внимание на различия в синтаксисе vs regular substr/instr.

+0

Спасибо за ответ. Это отлично работает и возвращает объект CLOB. Могу ли я вернуть строку из нее? – Usha

+0

Это было бы еще одним преимуществом использования 'dbms_lob.substr'; он берет входную строку 'CLOB' и выплевывает' VARCHAR2'. Интересно, что это задокументировано, в то время как я не смог быстро увидеть в документации Oracle, где он говорит, что стандартный 'substr' на' CLOB' возвращает 'CLOB' (но, конечно, я вам верю). – mathguy

0

На всякий случай вы просто пытаетесь разобрать длинную строку в соответствии с вашим примером. Включите «уровень» в выборе, если вам нужно увидеть индекс индекса в списке:

SQL> with tbl(str) as (
    select 'ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmI 
d12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:P 
mId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0,ABCDEF:PmId12345RmLn1VlId0' 
     from dual 
    ) 
    select regexp_substr(str, '(.*?)(,|$)', 1, level, NULL, 1) column_name 
    from tbl 
    connect by regexp_substr(str, '(.*?)(,|$)', 1, level) is not null; 

COLUMN_NAME 
-------------------------------------------------------------------------------- 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 
ABCDEF:PmId12345RmLn1VlId0 

16 rows selected. 

SQL> 
+0

Это дает проблему с производительностью, когда мы используем предложение connect by. – Usha

+0

Это было в случае, если вы действительно работали со строкой, а не с клобом. –