2017-05-15 45 views
0

我有一個包含巨大clob列的表。 有此列中的座標,可以有300.000數量座標用逗號分隔這樣29.0000, 40.0000 | 29.0001, 40.0000 | 29.0002, 40.0000Oracle - 如何解析選擇語句中的巨大clob列

我需要看到一個選擇輸出特定行像

1 | 29.0000, 40.0000 
2 | 29.0001 , 40.0000 
3 | 29.0002 , 40.0000 

我怎樣才能做到這一點?

回答

0

您可以創建一個用戶定義的函數生成座標的用戶定義的集合:

甲骨文設置

CREATE TYPE coordinate_type IS OBJECT(
    x NUMBER, 
    y NUMBER 
); 
/

CREATE TYPE coordinate_table IS TABLE OF coordinate_type; 
/

CREATE FUNCTION splitCoordinateList(
    i_string CLOB, 
    i_delimiter VARCHAR2 := '|', 
    i_separator VARCHAR2 := ',' 
) RETURN coordinate_table DETERMINISTIC PIPELINED 
AS 
    p_start PLS_INTEGER := 1; 
    p_end  PLS_INTEGER; 
    p_sep  PLS_INTEGER; 
    c_del_len CONSTANT PLS_INTEGER := LENGTH(i_delimiter); 
    c_sep_len CONSTANT PLS_INTEGER := LENGTH(i_separator); 
BEGIN 
    IF i_delimiter IS NULL OR c_del_len = 0 THEN 
    RETURN; 
    END IF; 

    IF i_separator IS NULL OR c_sep_len = 0 THEN 
    RETURN; 
    END IF; 

    LOOP 
    p_end := INSTR(i_string, i_delimiter, p_start); 
    EXIT WHEN p_end = 0; 
    p_sep := INSTR(i_string, i_separator, p_start); 
    IF p_sep = 0 OR p_sep >= p_end THEN 
     RAISE_APPLICATION_ERROR(-20001, 'Co-ordinate separator not found'); 
    END IF; 
    PIPE ROW(
     coordinate_type(
     TO_NUMBER(SUBSTR(i_string, p_start, p_sep - p_start)), 
     TO_NUMBER(SUBSTR(i_string, p_sep + c_sep_len, p_end - p_sep - c_sep_len)) 
    ) 
    ); 
    p_start := p_end + c_del_len; 
    END LOOP; 
    p_end := LENGTH(i_string); 
    IF p_start < p_end THEN 
    p_sep := INSTR(i_string, i_separator, p_start); 
    IF p_sep = 0 THEN 
     RETURN; 
    END IF; 
    PIPE ROW(
     coordinate_type(
     TO_NUMBER(SUBSTR(i_string, p_start, p_sep - p_start)), 
     TO_NUMBER(SUBSTR(i_string, p_sep + c_sep_len, p_end + 1 - p_sep - c_sep_len)) 
    ) 
    ); 
    END IF; 
END splitCoordinateList; 
/

查詢

SELECT ROWNUM, t.* 
FROM TABLE(splitCoordinateList(
     '29.0000, 40.0000 | 29.0001, 40.0000 | 29.0002, 40.0000' 
     )) t; 

輸出

ROWNUM  X  Y 
------ ------- ------- 
    1  29  40 
    2 29.0001  40 
    3 29.0002  40 
0

你可以使用這個簡單的SQL得到上述結果:

SELECT to_char( LEVEL 
      || '|' 
      || TRIM (
       REGEXP_SUBSTR (
        col, 
        '[^|]+', 
        1, 
        LEVEL))) 
       Col 
     FROM clob_tbl 
    CONNECT BY LEVEL <= 
       REGEXP_COUNT (
       col, 
       ',') ;  

演示:

SQL> create table clob_tbl(col clob); 

SQL> select * from clob_tbl; 

COL 
-------------------------------------------------------------------------------- 
29.0000, 40.0000 | 29.0001, 40.0000 | 29.0002, 40.0000 


SQL> SELECT to_char( LEVEL 
      || '|' 
      || TRIM (
       REGEXP_SUBSTR (
        col, 
         '[^|]+', 
        1, 
        LEVEL))) 
       Col 
     FROM clob_tbl 
    CONNECT BY LEVEL <= 
       REGEXP_COUNT (
       col, 
        ',') ; 

COL 
-------------------------------------------------------------------------------- 
1|29.0000, 40.0000 
2|29.0001, 40.0000 
3|29.0002, 40.0000 

SQL> 
+0

這是否有一個單行輸入(否則只會工作'CONNECT BY'子句將嘗試在輸出中交叉連接具有不同根的行,並隨着它下降層次結構而生成數量呈指數增長的重複行數)。 – MT0

+0

@ MT0。不確定行爲數據如何存在。對我來說,它假設數據是連續存在的,因爲它是一個巨大的clob。但是我不確定數據是如何存在的。 OP必須提供更多的說明 – XING