2017-02-22 131 views
2

我有以下字符串這樣劃分逗號分隔的串入列與空字符串

str:=',1,,3,4,5,6,,8,9'; 
str2:=',a,l,,gj,,b'; 

我怎麼可以把逗號分離串入這樣的列只使用SQL? (順序應該是下同)

COL 
--------- 
NULL 
1 
NULL 
3 
4 
5 
6 
NULL 
8 
9 

COL2 
---------- 
NULL 
a 
l 
NULL 
gj 
NULL 
b 

感謝

+0

只需要轉換一行? – GurV

+0

逗號的數量是否已知最大值? –

+0

您正在使用哪個版本的Oracle? – GurV

回答

1

您可以使用cross apply具有層次connect by來實現這一目標:

with t (text) as (select ',1,,3,4,5,6,,8,9' from dual union all 
        select ',1,,2' from dual) 
select regexp_substr(text, '[^,]+', 1, lvl) x 
from t cross apply (
    select level lvl 
    from dual 
    connect by level <= regexp_count(t.text, ',') + 1 
    ); 

上面的作品可以同時處理多行。

如果你只有一個行轉換,使用方法:

with t (text) as (select ',1,,3,4,5,6,,8,9' from dual) 
select 
    regexp_substr(text, '[^,]+', 1, level) x 
from t connect by level <= regexp_count(text, ',') + 1; 

如果你想要得到的結果相同順序輸入字符串發生,試試這個:

with t (text) as (select ',1,,3,4,5,6,,8,9' from dual union all 
        select ',1,,2' from dual) 
select replace(regexp_substr(text, '[^,]*,?', 1, lvl),',') x 
from t cross apply (
    select level lvl 
    from dual 
    connect by level <= regexp_count(t.text, ',') + 1 
    ); 

如果您的分隔符是^|{,請確保您正確地轉義特殊字符。試試這個:

with t (text) as (select '^|{1^|{^|{3^|{4^|{5^|{6^|{^|{8^|{9' from dual union all 
        select '^|{1^|{^|{2' from dual) 
select replace(regexp_substr(text, '[^(\^\|\{)]*(\^\|\{)?', 1, lvl),'^|{') x 
from t cross apply (
    select level lvl 
    from dual 
    connect by level <= regexp_count(t.text, '\^\|\{') + 1 
    ); 
+0

謝謝你的ans,但是結果與上面提到的不一樣。 –

+0

需要按順序,如下(NULL,1,NULL,3,4,5,6,NULL,8,9) –

+0

工作就像一個魅力。謝謝! –

-1

使用像波紋管:

declare @ids varchar(max), @xml XML 
       set @ids='135,136' 
       SET @xml = cast(('<X>' + replace(@ids, ',', '</X><X>') + '</X>') as xml) 


       SELECT xmlNode.value('.', 'varchar(50)') 
       FROM @xml.nodes('X') as T(xmlNode) 
+0

請將第一行代碼縮進4位,因此它將顯示爲代碼 –

+2

問題在於Oracle,所以此語法無效。 –

0

regex_replace +連接通過做你需要什麼,但不包括NULL值,所以需要以避免從正則表達式的輸出代替空字符串一招。在這種情況下,我在每個','之前向輸入添加一個#字符,然後在regex_replace完成任務後將其刪除。

您可以用下面的嘗試(這當然是一列的查詢,你只需要複製它的第二個)

select 
replace(result,'#','') from 
(select 
regexp_substr(replace(',SMITH,ALLEN,WARD,JONES',',','#,'),'[^,]+',1,level) result from dual 
connect by regexp_substr(replace(',SMITH,ALLEN,WARD,JONES',',','#,'), '[^,]+', 1, level) is not null 
); 
0

這裏是另外一個使用xmltable

SELECT DECODE (column_value, '-~-', NULL, COLUMN_VALUE) 
FROM xmltable(('"' || REPLACE(REGEXP_REPLACE(',1,,3,4,5,6,,8,9','^,|,$|,,', ',-~-,'), 
       ',', '","') || '"')) 

如果你需要一個文字NULL

SELECT TRIM(column_value) 
FROM xmltable(('"' || REPLACE(REGEXP_REPLACE(',1,,3,4,5,6,,8,9','^,|,$|,,', ',NULL,'), 
       ',', '","') || '"')) 

結果

NULL 
1 
NULL 
3 
4 
5 
6 
NULL 
8 
9 
0

使用遞歸子查詢保條款(亦稱公共表格表達);這裏是一個使用簡單的字符串函數和不依賴於(昂貴的)正則表達式的例子:

樣本數據

CREATE TABLE table_name (id, list) AS 
SELECT 1, 'a,b,c,d' FROM DUAL UNION ALL -- Multiple items in the list 
SELECT 2, 'e'  FROM DUAL UNION ALL -- Single item in the list 
SELECT 3, NULL  FROM DUAL UNION ALL -- NULL list 
SELECT 4, 'f,,g' FROM DUAL;   -- NULL item in the list 

查詢

WITH bounds (id, list, start_pos, end_pos, lvl) AS (
    SELECT id, list, 1, INSTR(list, ','), 1 FROM table_name 
UNION ALL 
    SELECT id, 
     list, 
     end_pos + 1, 
     INSTR(list, ',', end_pos + 1), 
     lvl + 1 
    FROM bounds 
    WHERE end_pos > 0 
) 
SELECT id, 
     SUBSTR(
     list, 
     start_pos, 
     CASE end_pos 
      WHEN 0 
      THEN LENGTH(list) + 1 
      ELSE end_pos 
     END - start_pos 
     ) AS item, 
     lvl 
FROM bounds 
ORDER BY id, lvl; 

輸出

 ID ITEM   LVL 
---------- ------- ---------- 
     1 a    1 
     1 b    2 
     1 c    3 
     1 d    4 
     2 e    1 
     3 (NULL)   1 
     4 f    1 
     4 (NULL)   2 
     4 g    3