2010-04-13 250 views
2

我有一列用逗號分隔的值,如6,7,99.3334逗號逗號分隔值在Oracle中

我需要編寫一個PL SQL過程,它將單獨給我這些值。列的長度是40.

任何人都可以幫助我嗎?

+0

看一看此鏈接:http://www.orafaq.com/forum/t/11692/2/ – 2010-04-13 08:14:23

回答

2

也許這樣的事情?

with my as (
    select '6,7,99.3334' str 
    from dual 
) 
select 
    regexp_substr(my.str,'[^,]+',1,level) part 
from my 
connect by level <= length(regexp_replace(my.str,'[^,]+')) + 1 
; 
1

對於非正則表達式的答案...

SELECT rn 
    , field 
    , SUBSTR(','||field||',' 
      , INSTR(','||field||',', ',', 1, rn) + 1 
      , INSTR(','||field||',', ',', 1, rn+1) 
       - INSTR(','||field||',', ',', 1, rn) 
       - 1 
      ) separated_field 
    FROM (SELECT LEVEL rn FROM dual CONNECT BY LEVEL <= 40) -- Length of column 
    , (SELECT '6,7,99.3334' field FROM dual) -- Source column 
WHERE rn <= ( LENGTH(field) 
       - LENGTH(REPLACE(field, ',', NULL)) 
      ) + 1 -- Number of Commas plus one 
0

這裏的另一種方法。這將您的字符串解析爲PL/SQL表。

首先創建一個定製的類型,是數字數組:

CREATE OR REPLACE TYPE number_tab AS TABLE OF NUMBER; 

然後創建其中逗號分隔值的列表轉換爲一個實例的數組類型的函數:

CREATE OR REPLACE FUNCTION csv_to_number_tab(p_string IN VARCHAR2) 
    RETURN number_tab AS 
    l_string  LONG DEFAULT p_string || ','; 
    l_data   number_tab := number_tab(); 
    n    NUMBER; 
BEGIN 
    LOOP 
     EXIT WHEN l_string IS NULL; 
     n := INSTR(l_string, ','); 
     l_data.EXTEND; 
     l_data(l_data.COUNT) := TO_NUMBER(LTRIM(RTRIM(SUBSTR(l_string, 1, n - 1)))); 
     l_string := SUBSTR(l_string, n + 1); 
    END LOOP; 

    RETURN l_data; 
END; 

這是一個匿名塊,它演示瞭如何使用:

DECLARE 
    nt number_tab := number_tab(); 
    i NUMBER := 0; 
BEGIN 
    nt := csv_to_number_tab('1,2.3, 456.7, 89.1234,567890.12345'); 

    FOR i IN 1 .. nt.COUNT LOOP 
     DBMS_OUTPUT.put_line(i || ' : ' || nt(i)); 
    END LOOP; 
END; 

請注意,有ar一些價值之間的空間,但不是其他的價值;該函數可以處理它。

1

這裏是將CSV列拆分成多個行的視圖:其中TT是你的表

CREATE OR REPLACE VIEW your_view AS 
SELECT tt.ID, SUBSTR(value, sp, ep-sp) split, other_col1, other_col2... 
    FROM (SELECT id, value 
      , INSTR(','||value, ',', 1, L) sp -- 1st posn of substr at this level 
      , INSTR(value||',', ',', 1, L) ep -- posn of delimiter at this level 
      FROM tt JOIN (SELECT LEVEL L FROM dual CONNECT BY LEVEL < 20) q -- 20 is max #substrings 
        ON LENGTH(value)-LENGTH(REPLACE(value,','))+1 >= L 
) qq JOIN tt on qq.id = tt.id; 

適用於長度超過1或null的csv值。 CONNECT BY LEVEL20是任意的,根據您的情況進行調整。

舉例說明:

SQL> CREATE TABLE tt (ID INTEGER, c VARCHAR2(20), othercol VARCHAR2(20)); 

    Table created 
    SQL> INSERT INTO tt VALUES (1, 'a,b,c', 'val1'); 

    1 row inserted 
    SQL> INSERT INTO tt VALUES (2, 'd,e,f,g', 'val2'); 

    1 row inserted 
    SQL> INSERT INTO tt VALUES (3, 'a,f', 'val3'); 

    1 row inserted 
    SQL> INSERT INTO tt VALUES (4,'aa,bbb,cccc', 'val4'); 

    1 row inserted 
    SQL> CREATE OR REPLACE VIEW myview AS 
     2 SELECT tt.ID, SUBSTR(c, sp, ep-sp+1) splitval, othercol 
     3 FROM (SELECT ID 
     4    , INSTR(','||c,',',1,L) sp, INSTR(c||',',',',1,L)-1 ep 
     5   FROM tt JOIN (SELECT LEVEL L FROM dual CONNECT BY LEVEL < 20) q 
     6      ON LENGTH(c)-LENGTH(REPLACE(c,','))+1 >= L 
     7 ) q JOIN tt ON q.id =tt.id; 

    View created 
    SQL> select * from myview order by 1,2; 

            ID SPLITVAL    OTHERCOL 
--------------------------------------- -------------------- -------------------- 
             1 a     val1 
             1 b     val1 
             1 c     val1 
             2 d     val2 
             2 e     val2 
             2 f     val2 
             2 g     val2 
             3 a     val3 
             3 f     val3 
             4 aa     val4 
             4 bbb     val4 
             4 cccc     val4 

12 rows selected 

SQL>