2017-02-15 33 views
-2

カンマ区切りの値を含むデータベース列があります。 Oracleで正規表現を使用せずに、この列から個々の値を別の行に取得する方法はありますか。Oracleでカンマ区切りの値を区切ります

+0

いただきましたか? – user648026

+1

もちろん、SUBSTRとINSTR(そしておそらくLENGTH)を使うだけです。あなたもSOで検索しましたか?多くの例が見つかります。 – mathguy

+0

正規表現を使用しない場合、おそらく 'regex'タグは必要ありません。 – BriteSponge

答えて

0

SO postは、regexp_substrの代わりにXMLを使用しています。

EDITを助け

希望:リンクに従うことをしたくない人のためには、簡単な例は次のようになります。

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ソリューションのように。しかし、このアプローチではregexpを要求どおりに使用していません。

+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) 

が出力:REGEXP_SUBSTRと間違っ

 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