2010-04-13 249 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>