2011-09-20 45 views
2

我有表:的Oracle 11g拆分文本列行

ID |Values 
-----+-------------------------------- 
1 |AB,AD 
2 |AG, ... ,BD 
3 |AV 

我怎样才能把它转换为:

ID |Value 
-----+------ 
1 |AB 
1 |AD 
2 |AG 
... |... 
2 |BD 
3 |AV 
+0

我使用一个select语句 – spiaire

+0

可怕的DB设计做到这一点,存储分隔字符串中的值。建议您的应用程序设计者(或DBA)在插入数据库之前分割字符串。 – Ollie

+0

@Ollie和downvoters:这并不罕见。这实际上是一个很好的问题 –

回答

6

使用内置的XML功能,你可以做这样的:

with sample_data as 
(
select 1 id, 'AB,AD' vals from dual union all 
select 2, 'AG,AK,AJ,BA,BD' from dual union all 
select 3, 'AV' from dual 
) 
select id, cast(t.column_value.extract('//text()') as varchar2(10)) val 
    from sample_data, 
    table(xmlsequence(xmltype(
    '<x><x>' || replace(vals, ',', '</x><x>') || '</x></x>' 
).extract('//x/*'))) t; 

结果:

ID VAL 
--- ----- 
1 AB 
1 AD 
2 AG 
2 AK 
2 AJ 
2 BA 
2 BD 
3 AV 
+0

+1,XML功能非常适合这样做。 – Ollie

2

使用递归公用表表达式,相同的查询看起来是这样的:

with sample_data as 
(
    select 1 id, 'AB,AD' vals from dual union all 
    select 2, 'AG,AK,AJ,BA,BD' from dual union all 
    select 3, 'AV' from dual 
), 
split_first(id, val, rem) as 
(
    select id, 
    coalesce(substr(vals, 1, instr(vals, ',') - 1), vals) val, 
    case when instr(vals, ',') > 0 then substr(vals, instr(vals, ',') + 1) end rem 
    from sample_data 
    union all 
    select id, 
    coalesce(substr(rem, 1, instr(rem, ',') - 1), rem) val, 
    case when instr(rem, ',') > 0 then substr(rem, instr(rem, ',') + 1) end rem 
    from split_first 
    where rem is not null 
) 
select id, val from split_first 
order by id; 

或者稍微不同的方法:

with sample_data as 
(
    select 1 id, 'AB,AD' vals from dual union all 
    select 2, 'AG,AK,AJ,BA,BD' from dual union all 
    select 3, 'AV' from dual 
), 
pos(id, seq, vals, sta, stp) as 
(
    select id, 1, vals, 1, instr(vals, ',') from sample_data 
    union all 
    select id, seq + 1, vals, stp + 1, instr(vals, ',', stp + 1) from pos 
    where stp > 0 
) 
select id, substr(vals, sta, case when stp > 0 then stp - sta else length(vals) end) from pos 
order by id, seq; 
+0

哪种解决方案更高效? – spiaire

+0

I/O明智,它应该没有任何区别,因为相同的行被处理。 CPU聪明的第二个查询可能更有效,因为它使用较少的字符串操作。 – Codo