2015-09-18 2 views
1

Я следовал инструкциям, изложенным в этой статье, чтобы разделить строки с разделителями в строках таблицы:SQL REGEXP_SUBSTR возвращает пустую строку при разделении

Splitting string into multiple rows in Oracle

Ответ, который работал в этой конкретной разделителями строки представлена ​​в это скрипка:

Demo1

with temp as 
(
    select 108 Name, 'test' Project, 'Err1, Err2, Err3' Error from dual 
    union all 
    select 109, 'test2', 'Err1' from dual 
) 
select distinct 
    t.name, t.project, 
    trim(regexp_substr(t.error, '[^,]+', 1, levels.column_value)) as error 
from 
    temp t, 
    table(cast(multiset(select level from dual connect by level <= length (
     regexp_replace(t.error, '[^,]+')) + 1) as sys.OdciNumberList)) levels 
order by name; 

К сожалению, моя строка не с запятой. Он разделен подстрокой ':::'. Я пытался изменить ответ, чтобы удовлетворить мою ситуацию, написав SQL в следующей скрипке:

Demo2

with temp as 
(
    select 108 Name, 'test' Project, 'Err1:::Err2:::Err3' Error from dual 
    union all 
    select 109, 'test2', 'Err1' from dual 
) 
select distinct 
    t.name, t.project, 
    trim(regexp_substr(t.error, '[^:::]+', 1, levels.column_value)) as error 
from 
    temp t, 
    table(cast(multiset(select level from dual connect by level <= length (
     regexp_replace(t.error, '[^:::]+')) + 1) as sys.OdciNumberList)) levels 
order by name 

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

Может ли кто-нибудь помочь мне понять, почему изменения, которые я сделал, будут производить эту постороннюю строку с нулевым значением?

ответ

0

Просто используйте REPLACE и ваш стандартный код с ,

SqlFiddleDemo

with temp as 
(
    select 108 Name, 'test' Project, 'Err1:::Err2:::Err3' Error from dual 
    union all 
    select 109, 'test2', 'Err1' from dual 
) 
select distinct 
    t.name, t.project, 
    trim(regexp_substr(REPLACE(t.error, ':::', ', '), '[^,]+', 1, levels.column_value)) as error 
from 
    temp t, 
    table(cast(multiset(select level from dual connect by level <= length (regexp_replace(REPLACE(t.error, ':::', ', '), '[^,]+')) + 1) as sys.OdciNumberList)) levels 
order by name 

Или вам нужно разделить на длину разделители:

SqlFiddle

with temp as 
(
    select 108 Name, 'test' Project, 'Err1:::Err2:::Err3' Error from dual 
    union all 
    select 109, 'test2', 'Err1:::Err2' from dual 
) 
select distinct 
    t.name, t.project, 
    trim(regexp_substr(t.error, '[^:::]+', 1, levels.column_value)) as error 
from 
    temp t, 
    table(cast(multiset(select level from dual connect by level <= length (
     regexp_replace(t.error, '[^:::]+'))/3 + 1) as sys.OdciNumberList)) levels 
order by name 

Вы можете увидеть, почему выполнение:

SELECT length (regexp_replace('Err1:::Err2:::Err3', '[^:::]+')) + 1 AS l 
FROM dual 

Это вернет 7 и ваш:

SELECT DISTINCT t.name, t.project, 
trim(regexp_substr(t.error, '[^:::]+', 1, levels.column_value)) as error 

будет пытаться получить regexp_substr 7 вхождений, где 4 из них будет NULL и в конец 4 NULL будет раздавлен до одного NULL по DISTINCT.

+0

@LeeFowler См. Мой обновленный ответ – lad2025

Смежные вопросы