2014-09-01 45 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如何處理這個。