2017-02-15 149 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