SYS_REFCURSOR out 参数 - 运行存储过程失败

Posted

技术标签:

【中文标题】SYS_REFCURSOR out 参数 - 运行存储过程失败【英文标题】:SYS_REFCURSOR out parameter - running stored procedure fails 【发布时间】:2016-07-19 15:53:49 【问题描述】:

我来自 SQL Server 背景,但我在 Oracle 中遇到了这个问题。数据库中所有已配置的存储过程都需要传入类型为“sys_refcursor”的参数。简而言之,他们这样做(存储过程要复杂得多,但整个光标就是我要了解的):

CREATE OR REPLACE PROCEDURE xxx_API_TEST 
(
  TESTCURSOR OUT SYS_REFCURSOR 
) AS 
BEGIN
  OPEN CURS FOR
  SELECT * FROM SOMETABLE;
END xxx_API_TEST;

所以 - 在 Oracle SQL Developer 中我可以毫无问题地运行它 - 并在“输出变量”窗口中查看光标的输出。

但是,不必每次我想重新测试时都重新加载对话框 - 我认为可以将对话框中的 PL/SQL 复制到新工作表,然后根据需要运行它to - 调整参数以适应 - 所以在这种情况下,我会运行:

    DECLARE
      TESTCURSOR SYS_REFCURSOR;
    BEGIN

      xxx_API_TEST(
        TESTCURSOR => TESTCURSOR 
      );
      /* Legacy output: 
    DBMS_OUTPUT.PUT_LINE('TESTCURSOR = ' || TESTCURSOR );
    */ 
      :TESTCURSOR := TESTCURSOR; --<-- Cursor
    --rollback; 
    END;

这与运行对话框中显示的完全相同。

但是,如果我这样做 - 它只会引发错误 - 说明:

Error starting at line : 1 in command -
<snip>
Error report -
ORA-06550: line 11, column 20:
PLS-00382: expression is of wrong type
ORA-06550: line 11, column 3:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

我不知道如何诊断这个。它在对话框中运行良好但在工作表中运行良好的事实令人费解 - 检查发送到数据库的内容我看不出它实际使用的 SQL 有任何差异。

有趣的是,如果我从工作表中运行此代码 - 它会弹出一个对话框来询问 TESTCURSOR 的值 - “运行”对话框没有这样做。我只是按 OK - 但我尝试勾选和取消勾选“Null”复选框均无济于事。

非常感谢任何帮助。它是甲骨文 12c。如果您需要更多信息,请告诉我。

干杯, 托尼


更新:2016 年 7 月 20 日

我最终将值从 fetch 中提取到变量中,然后转储到 dbms_output - 这为我提供了重复运行相同存储过程所需的内容。 例如

loop 
    fetch testcursor into Res, ActDate<snip>;  

    exit when testcursor%notfound;  

    DBMS_OUTPUT.PUT_LINE(Res || ' | ' || ActDate etc etc);  

  end loop;  
  close testcursor;

【问题讨论】:

【参考方案1】:

运行对话框是根据过程规范生成的,因此知道testcursor 的正确类型,但是当您将其粘贴到工作表中时它不会,并且似乎将其定义为文本字符串。从 SQL Developer 4.0.3.16 开始,工作表绑定值提示似乎无法更改数据类型。

至于如何在 SQL Dev 中创建带有游标输出的可重用测试脚本,我不知道。 (我通常使用 PL/SQL Developer 可以做到这一点,但它不是免费软件。)

编辑:在这个线程中,一个解决方案是编写一个包装函数并从对偶中选择它。我刚刚试过,你没有得到一个网格,但是你得到了一种调试输出而不需要太多的努力:

Oracle SQL Developer: Show REFCURSOR Results in Grid?

【讨论】:

谢谢威廉 - 至少我不会发疯。最终只是像上面一样运行它,但是为每一列获取变量,例如loop fetch testcursor into Res, ActDate&lt;snip&gt;; exit when testcursor%notfound; DBMS_OUTPUT.PUT_LINE(Res || ' | ' || ActDate etc etc); end loop; close testcursor; 我已经更新了我的答案,提供了一个可能有帮助的早期问题的链接。那里的建议是将过程包装在一个函数中并从对偶中选择它。

以上是关于SYS_REFCURSOR out 参数 - 运行存储过程失败的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 out sys_refcursor 参数执行 oracle 过程?

创建具有 SYS_REFCURSOR 作为输出参数的 mysql 过程时出错

无法在实体框架中映射 SYS_REFCURSOR

使用 SYS_REFCURSOR OUT 调用过程

JPA 实体的 Oracle OUT SYS_REFCURSOR 始终为空

使用 FOR UPDATE SKIP LOCKED 打开 OUT SYS_REFCURSOR 时出错