我有一个包含逗号分隔值的数据库列。有没有办法在不使用Oracle中的正则表达式的情况下将此列中的各个值转换为不同的行。
答案 0 :(得分: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
答案 1 :(得分: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
正如regexp解决方案一样存在局限性。但是这种方法并没有按要求使用正则表达式。