2017-02-15 5 views
-2

Ich habe eine Datenbankspalte, die durch Komma getrennte Werte enthält. Gibt es eine Möglichkeit, die einzelnen Werte aus dieser Spalte in verschiedenen Zeilen zu erhalten, ohne regulären Ausdruck in Oracle zu verwenden.Separate Komma getrennte Werte in Oracle

+0

Was stimmt nicht mit REGEXP_SUBSTR? – user648026

+1

Natürlich gibt es, verwenden Sie einfach SUBSTR und INSTR (und möglicherweise LÄNGE). Hast du eine Suche gemacht, auch hier auf SO - du solltest viele Beispiele finden. – mathguy

+0

Wenn kein regulärer Ausdruck verwendet wird, ist das 'Regex'-Tag möglicherweise nicht erforderlich. – BriteSponge

Antwort

0

Hier ist eine SO post, die XML statt regexp_substr verwendet.

Hoffnung, die

EDIT hilft: Für diejenigen, die nicht wollen, dem Link zu folgen, ein einfaches Beispiel wäre:

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; 

Ausgang:

TOKENS 
a 
test 
string 
for 
splitting 
values 

Es Einschränkungen genau wie mit Regexp-Lösung. Bei diesem Ansatz wird regexp jedoch nicht wie angefordert verwendet.

+0

Wer kümmert sich um den Downvote? – tbone

+0

Link nur antworten? Nur eine Schätzung – APC

+0

Vielleicht APC. Vielleicht ist es besser, nur zu kopieren/einfügen;) Danke für die Köpfe hoch – tbone

3

Erstellen Sie eine kleine Funktion, die die getrennte Liste zu einer Sammlung umwandelt und dann verwenden, um eine TABLE() Sammlung Ausdruck sie als separate Zeilen enthalten:

PL/SQL-Funktion:

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; 
/

Probe Daten:

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 

Abfrage:

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) 

Ausgang:

 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 
Verwandte Themen