2014-09-01 55 views
0

我有2个表AB。表A中的数据有一个字符串,我想根据"#___-"abc,xyz,efg等)拆分成不同的列,并将其复制到表B。表A的字符串大小将每一行将可变长度字符串分为多列

表A变化:

ID | ABC    | XYZ     | EFG 
    --------------------------------------------------------------- 
    101 | sds)dfgd)3453) | hju)dddjfj)eieei)2323 | 
    102 | ddeff)errr)3434) | bnhb)hehe)333)   | 3434)34 
    102 | dew)weerr)2343) | bnhb)hehe)333)   | 3434)34 

我想正则表达式,但因为字符串的大小可能会有所不同,因为:

Create table A (data varchar(100)); 

Insert table A 
    values ('101,#abc-sds)dfgd)3453)#xyz-hju)dddjfj)eieei)2323'); 
Insert into A 
    values ('102,#abc-ddeff)errr)3434)#xyz-bnhb)hehe)333)#abc-dew)weerr)2343)#efg-3434)34'); 

Create table B (id number, abc varchar2(50), xyz varchar2(50), 
    efg varchar2(50)); 

表B的输出重复发生我不能进一步任何帮助将不胜感激。

+0

不明白如何分割,标记是什么,显示更多示例以及如何分割它。 – zaratustra 2014-09-01 10:44:00

+2

你想将一个字符串拆分为多行*和*列?为什么在两行中重复102的xyz/efg值 - 如果'#abc'是下一个'行'的开始,是不是一行会得到xyz,另一行是efg?你的正则表达式尝试有多远? – 2014-09-01 10:45:07

回答

0

如果你问我想你问,你需要动态SQL正则表达式枢转动态SQL生成代码,该代码将生成具有适当列的表格(因为它们以#___-命名,并且有任意数量的字段)。 旋转将一列值转换为每个ID的行。

我习惯于SQL Server,而不是Oracle,而我使用的正则表达式功能是UDF,因为SQL Server没有本地Regex功能。所以我的答案只会帮助很多,但可能会给你一个如何解决这个问题的想法。

我想你可以内置在甲骨文正则表达式UDF,我们的正则表达式UDF返回结果集,我可以join或SQL Server的情况下cross/outer apply,这让我Value varchar与整场比赛和SubMatches xml所捕获的子匹配:

create table #A (data varchar(100)); 

Insert into #A 
    values ('101,#abc-sds)dfgd)3453)#xyz-hju)dddjfj)eieei)2323'); 
Insert into #A 
    values ('102,#abc-ddeff)errr)3434)#xyz-bnhb)hehe)333)#abc-dew)weerr)2343)#efg-3434)34'); 

declare @cols nvarchar(max), @q nvarchar(max) 


    -- Gets found columns comma-separated in @cols: 
select @cols = isnull(@cols + ', ', '') + substring(r.Value, 2, len(r.Value)-2) 
from #A 
cross apply dbo.RegexFind(data, '#(\w+)-', 1, 1, 1) r 
group by r.Value 


    -- Dynamically create #B with @cols and insert 
set @q = N'create table #B(id int, ' + replace(@cols, ', ', ' varchar(255), ') + ' varchar(255)) 
insert into #B 
select p.* 
from (
    select r.Value, 
     a.SubMatches.value(''(//submatch[@index=0]/@value)[1]'', ''varchar(255)'') col, 
     a.SubMatches.value(''(//submatch[@index=1]/@value)[1]'', ''varchar(255)'') val 
    from #A 
     -- Find the ID at the start 
    cross apply dbo.RegexFind(data, ''^\d+'', 1, 1, 1) r 
     -- Find any and all #___- occurrences and the text after it 
    outer apply dbo.RegexFind(data, ''#(\w+)-([^#]+)'', 1, 1, 1) a 
) s 
pivot (-- Pivot dynamically on the found @cols 
    min(val) for col in (' + @cols + ') 
) p 
select * from #B' 

exec sp_executesql @q 

随着表#A您的示例内容这给下面的SQL(的@q含量):

create table #B(id int, abc varchar(255), efg varchar(255), xyz varchar(255)) 
insert into #B 
select p.* 
from (
    select r.Value, 
     a.SubMatches.value('(//submatch[@index=0]/@value)[1]', 'varchar(255)') col, 
     a.SubMatches.value('(//submatch[@index=1]/@value)[1]', 'varchar(255)') val 
    from #A 
     -- Find the ID at the start 
    cross apply dbo.RegexFind(data, '^\d+', 1, 1, 1) r 
     -- Find any and all #___- occurrences and the text after it 
    outer apply dbo.RegexFind(data, '#(\w+)-([^#]+)', 1, 1, 1) a 
) s 
pivot (-- Pivot dynamically on the found @cols 
    min(val) for col in (abc, efg, xyz) 
) p 
select * from #B 

注寿呃这个#B临时表只存在于动态SQL内部,我不知道Oracle如何处理这个。