如何在过程中使用返回Oracle REF_CURSOR的函数

时间:2011-11-22 15:46:40

标签: oracle plsql procedure

我必须编写一个Oracle程序,该程序应该调用返回REF_CURSOR的Oracle函数。该函数声明为

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;

你可以告诉我为了从我的程序中调用函数我需要编写什么吗?我想将所有返回的值(形成一个包含两列的表)插入到一个有理数的表中。

提前谢谢!

1 个答案:

答案 0 :(得分: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 COLLECTFORALL会更有效率。如果您只处理几千行(因为您的函数只是在分隔字符串中解析数据,我假设您期望返回相对较少的行),性能差异可能很小。但是,如果您正在处理更多数据,那么差异就会非常明显。根据Oracle版本和您的特定要求,您可以简化INSERT中的FORALL语句以插入记录,而不是单独列出记录中的每一列。

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;