2017-02-15 92 views
-2

我有一個包含逗號分隔值的數據庫列。有什麼方法可以在不使用Oracle中的正則表達式的情況下將此列中的各個值存入不同的行。Oracle中單獨的逗號分隔值

+0

哪些錯誤與REGEXP_SUBSTR? – user648026

+1

當然,只要使用SUBSTR和INSTR(可能還有LENGTH)。你做了搜索,即使在這裏 - 你應該找到很多例子。 – mathguy

+0

如果沒有使用正則表達式,那麼可能'正則表達式'標記不是必需的。 – BriteSponge

回答

0

這是一個使用XML而不是regexp_substr的SO post

希望幫助

編輯:對於那些不想跟隨鏈接誰,一個簡單的例子是:

with testdata as (
    select 'a,test,string,for,splitting,values' as col from dual 
) 
select extractvalue(x.column_value, 'e') as tokens 
from testdata, xmltable ('e' passing xmlparse(content '<e>' || replace(col, ',', '</e><e>') || '</e>')) x; 

輸出:

TOKENS 
a 
test 
string 
for 
splitting 
values 

有限制就像使用正則表達式解決方案一樣。但是這種方法不按要求使用正則表達式。

+0

任何人都在意解釋downvote? – tbone

+0

鏈接唯一的答案?只是猜測 – APC

+0

也許APC。也許它更好地複製/粘貼;)謝謝你的頭 – tbone

3

創建一個小功能,該分隔列表轉換爲一個集合,然後使用TABLE()集合表達式將它作爲獨立行:

PL/SQL函數

CREATE OR REPLACE FUNCTION split_String(
    i_str IN VARCHAR2, 
    i_delim IN VARCHAR2 DEFAULT ',' 
) RETURN SYS.ODCIVARCHAR2LIST DETERMINISTIC 
AS 
    p_result  SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST(); 
    p_start  NUMBER(5) := 1; 
    p_end   NUMBER(5); 
    c_len CONSTANT NUMBER(5) := LENGTH(i_str); 
    c_ld CONSTANT NUMBER(5) := LENGTH(i_delim); 
BEGIN 
    IF c_len > 0 THEN 
    p_end := INSTR(i_str, i_delim, p_start); 
    WHILE p_end > 0 LOOP 
     p_result.EXTEND; 
     p_result(p_result.COUNT) := SUBSTR(i_str, p_start, p_end - p_start); 
     p_start := p_end + c_ld; 
     p_end := INSTR(i_str, i_delim, p_start); 
    END LOOP; 
    IF p_start <= c_len + 1 THEN 
     p_result.EXTEND; 
     p_result(p_result.COUNT) := SUBSTR(i_str, p_start, c_len - p_start + 1); 
    END IF; 
    END IF; 
    RETURN p_result; 
END; 
/

樣品數據

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 

查詢

SELECT t.id, 
     v.column_value AS value, 
     ROW_NUMBER() OVER (PARTITION BY id ORDER BY ROWNUM) AS lvl 
FROM table_name t 
     LEFT OUTER JOIN 
     TABLE(split_String(t.list)) v 
     ON (1 = 1) 

輸出

 ID VALUE   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