2011-11-22 36 views
1

我必须编写一个Oracle过程,它应该调用返回REF_CURSOR的Oracle函数。功能是这样声明的如何使用函数在过程中返回Oracle REF_CURSOR

FUNCTION "IMPACTNET"."TF_CONVERTPARA" (PARASTRING IN NVARCHAR2) RETURN SYS_REFCURSOR 
AS 
    c SYS_REFCURSOR; 
BEGIN 
    OPEN c FOR   
     SELECT SUBSTR(element, 1, INSTR(element, '|') - 1)  as key, 
       SUBSTR(element, INSTR(element, '|') + 1, 99999) as val 
     FROM (
      SELECT REGEXP_SUBSTR(PARASTRING, '[^;]+', 1, LEVEL) element   
       FROM dual  
       CONNECT BY LEVEL < LENGTH(REGEXP_REPLACE(PARASTRING, '[^;]+')) + 1 
      ); 
    RETURN c;  
END; 

你能告诉我什么我需要编写以调用我的过程中的功能?我想插入所有返回的值(塑造一个有两列的表)到一个有理的表中。

预先感谢您!

回答

3

沿东西这行应该工作(显然,我猜对表名和列名和确切的逻辑,你想实现)

CREATE PROCEDURE some_procedure_name 
AS 
    l_rc SYS_REFCURSOR := impactnet.tf_convertpara(<<some string>>); 
    l_key VARCHAR2(100); 
    l_val VARCHAR2(100); 
BEGIN 
    LOOP 
    FETCH l_rc 
     INTO l_key, l_val; 
    EXIT WHEN l_rc%notfound; 

    INSERT INTO some_table(key_column, val_column) 
     VALUES(l_key, l_val); 
    END LOOP; 
END; 

由于奥利指出的,做一个BULK COLLECT和一个FORALL会更有效率。如果你只是处理几千行(因为你的函数只是用分隔字符串解析数据,我假设你期望返回相对较少的行),但性能差异可能是最小的。但是,如果您正在处理更多数据,则差异可能非常明显。根据Oracle版本和您的具体要求,您可以简化FORALL中的INSERT语句以插入记录,而不是单独列出记录中的每列。

CREATE PROCEDURE some_procedure_name 
AS 
    TYPE key_val_rec 
    IS RECORD( 
     key VARCHAR2(100), 
     val VARCHAR2(100) 
    ); 
    TYPE key_val_coll 
    IS TABLE OF key_val_rec; 

    l_rc SYS_REFCURSOR := impactnet.tf_convertpara(<<some string>>); 
    l_coll key_val_coll; 
BEGIN 
    LOOP 
    FETCH l_rc 
     BULK COLLECT INTO l_coll 
    LIMIT 100; 
    EXIT WHEN l_coll.count = 0; 

    FORALL i IN l_coll.FIRST .. l_coll.LAST 
     INSERT INTO some_table(key_column, val_column) 
     VALUES(l_coll(i).key, l_coll(i).val); 
    END LOOP; 
END; 
+0

对BULK COLLECT收集结果然后用FORALL插入它们不是更好吗? – Ollie

+0

很酷,它的作品!谢谢! – llasarov

+0

@Ollie - 这绝对会更有效率。我只是为了简单而不是表现。但我采纳了你的建议,并使用'BULK COLLECT'发布了一个例子 –

相关问题