2013-11-04 85 views
0

我已經在pl/sql中編寫了一個自定義函數,它根據提供的分隔符將clob變量拆分爲一組字符串,但它不能按預期工作,請幫助我用代碼來解決問題。自定義拆分功能不能在pl/sql中工作

create or replace 
FUNCTION        SPLITCLOB (p_in_string clob, p_delim VARCHAR2) RETURN t_array 
IS 
    i  number :=0; 
    pos  number :=0; 
    lv_str clob := p_in_string; 

    Strings t_array:=t_array(); 
Begin 
    -- determine first chuck of string 
    pos := DBMS_LOB.INSTR(lv_str,p_delim,1,1); 

    If (pos = 0) Then 
    i := i + 1; 
    strings.Extend(); 
    strings(i) := DBMS_LOB.SUBSTR(lv_str,1); 
    RETURN strings; 
    End If; 
    -- while there are chunks left, loop 
    WHILE (pos != 0) LOOP 
    -- increment counter 
    i := i + 1; 

    -- create array element for chuck of string 
    strings.EXTEND(); 
    strings(i) := DBMS_LOB.SUBSTR(lv_str,1,pos-1); 

    -- remove chunk from string 
    lv_str := DBMS_LOB.SUBSTR(lv_str,pos+1,dbms_lob.getLength(lv_str)); 

    -- determine next chunk 
    pos := DBMS_LOB.INSTR(lv_str,p_delim,1,1); 

    -- no last chunk, add to array 
    IF pos = 0 THEN 
     strings.extend(); 
     strings(i+1) := lv_str; 
    END IF; 
    End Loop; 

    -- return array 
    RETURN strings; 
End Splitclob; 

這裏t_array()是自定義類型defiition其中在預先設置

create or replace 
    TYPE "T_ARRAY" 
    AS TABLE OF VARCHAR2(500); 

感謝以下

+1

代碼有什麼問題? 你有什麼試圖解決它? 您嘗試從中提取數據的CLOB的內容是什麼? – Rene

+0

有一張表,其中有一個名爲description的列,其中clob作爲內容,基本上它包含我們用於分析的應用程序的audit_logs。在表中的描述是種類「order_id = 383325; order_line_item = 59; order_class_id = 5749; subscription_code = 5U12PFNCAU; start_date = 01/12/2012; end_date = 30/11/2013; date_override = null; license_available = -1; license_consumed = 1; license_override = -1; order_class_status = 0「 – Abhi

+0

我們試圖通過提供分隔符來獲取各種值」;「 。 – Abhi

回答

1

我很久以前改變了一段代碼,我寫的不是,似乎它可以按照你的想法工作。注意:如果輸入參數中只有一個項目(我的意思是輸入中沒有分隔符的情況),它也可以工作。

CREATE OR REPLACE 
    TYPE T_ARRAY 
    AS TABLE OF VARCHAR2(500); 
/

CREATE OR REPLACE FUNCTION splitclob (p_clob_in CLOB, p_delim VARCHAR2) RETURN t_array 
AS 
    v_buffer VARCHAR2(500); 
    v_len NUMBER; 
    v_offset NUMBER := 1; 
    v_delim_pos NUMBER; 
    v_amount NUMBER; 
    v_result_array t_array := t_array(); 
BEGIN 
    IF p_clob_in IS NOT NULL THEN 
    v_len := dbms_lob.getlength(p_clob_in); 

    WHILE v_offset < v_len 
    LOOP 
     v_delim_pos := instr(p_clob_in, p_delim, v_offset); 

     IF v_delim_pos = 0 THEN 
     v_amount := v_len - v_offset + 1; 
     ELSE 
     v_amount := v_delim_pos - v_offset; 
     END IF; 

     dbms_lob.read(p_clob_in, v_amount, v_offset, v_buffer); 
     v_offset := v_offset + v_amount + 1; 

     v_result_array.EXTEND; 
     v_result_array(v_result_array.LAST) := v_buffer; 
    END LOOP; 
    END IF; 

    RETURN v_result_array; 
END; 
/

DECLARE 
    v_array t_array; 
BEGIN 
    v_array := splitclob('order_id=383325; order_line_item=59; order_class_id=5749; subscription_code=5U12PFNCAU; start_date=01/12/2012; end_date=30/11/2013; date_override=null; license_available=-1; license_consumed=1; license_override=-1; order_class_status=0', ';'); 

    FOR v_i IN v_array.first..v_array.last 
    LOOP 
    dbms_output.put_line(v_i || ' ' || v_array(v_i)); 
    END LOOP; 
END; 
/

輸出:

1 order_id=383325 
2 order_line_item=59 
3 order_class_id=5749 
4 subscription_code=5U12PFNCAU 
5 start_date=01/12/2012 
6 end_date=30/11/2013 
7 date_override=null 
8 license_available=-1 
9 license_consumed=1 
10 license_override=-1 
11 order_class_status=0

你必須要考慮到的情況時的標記之一將是超過500個字符。請記住,SQL上下文中的VARCHAR2數據類型具有4000字節的限制。如果你知道不會有比這更長的令牌,那麼你不需要改變任何東西。

+0

在SQL,4000字節或字符中使用時不是限制Oracle VARCHAR2嗎?來源:http://docs.oracle.com/cd/E11882_01/server.112/e41085/sqlqr06002.htm#SQLQR966 –

+0

@IanCarpenter我想我把標準輸出的最大行長度與VARCHAR2的最大長度以字節爲單位混合起來,將會更新我的回答,謝謝。 –

+0

不用擔心,並提高了您的答案 –