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

Posted

技术标签:

【中文标题】如何在过程中使用返回 Oracle REF_CURSOR 的函数【英文标题】:How to use function returning Oracle REF_CURSOR in a procedure 【发布时间】:2011-11-22 15:46:40 【问题描述】:

我必须编写一个 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】:

类似的东西应该可以工作(显然,我猜测的是表名和列名以及您尝试实现的确切逻辑)

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;

正如 Ollie 指出的那样,执行 BULK COLLECTFORALL 会更有效。如果您只处理几千行(因为您的函数只是解析分隔字符串中的数据,我假设您希望返回相对较少的行),性能差异可能很小。但是,如果您要处理更多数据,则差异可能会非常明显。根据 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;

【讨论】:

批量收集结果然后使用 FORALL 一次性插入不是更好吗? @Ollie - 这绝对会更有效率。我追求简单而不是性能。但我采纳了您的建议并使用BULK COLLECT 发布了一个示例

以上是关于如何在过程中使用返回 Oracle REF_CURSOR 的函数的主要内容,如果未能解决你的问题,请参考以下文章

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

如何使用 RefCursor 返回类型测试 Oracle 存储过程?

oracle中的存储过程如何返回查询到的多个值?

如何使用 SELECT 从 Oracle 存储过程中返回行?

oracle如何执行存储过程以及如何返回一个table

如何在过程中返回一个oracle表