如何在 pl/sql 过程中使用游标返回多行和多列?

Posted

技术标签:

【中文标题】如何在 pl/sql 过程中使用游标返回多行和多列?【英文标题】:How to return multiple rows with multiple columns using cursor in pl/sql procedure? 【发布时间】:2018-08-14 13:53:32 【问题描述】:

我正在尝试为在特定日期之间注册课程的返回用户编写一个过程(在 PL/SQL 中)。将有 2 个输入(date1、date2)和 3 个输出(enrollno、error_code 和enroll_date)。我希望它显示在 date1 和 date2 之间注册的多行用户的信息。这是我第一次编写程序,我能够以一种可以返回一行的方式编写它。但由于在这些日期之间可能有很多用户注册,我想显示很多行。我看到我可以使用 sys_refcursor 但我做不到。互联网上的示例主要用于一个输出程序,因此我无法将它们改编为我的。

例如,我查看了此处的示例 https://oracle-base.com/articles/misc/using-ref-cursors-to-return-recordsets,但我对声明语句感到困惑。

编辑:我打算从 Java 代码中调用此过程并将返回的结果分配给某些东西,并且不允许将新表添加到数据库中。

这是我的程序:

create or replace procedure display_users(pi_date1       in date,
                                          pi_date2       in date,
                                          po_enrollno    out number,
                                          po_error_code  out varchar2,
                                          po_enroll_date out date) is
  cursor user_display is
    select u.enrollno, u.error_code, u.enroll_date,
      from user_table u
     where u.enroll_date between pi_date1 and pi_date2;

begin
  open user_display;
  loop
    fetch user_display
      into po_enrollno, po_error_code, po_enroll_date;
    EXIT WHEN user_display%notfound;

  end loop;
  close user_display;

end;

【问题讨论】:

【参考方案1】:

您可以使用单个 REFCURSOR 输出参数而不是多个输出参数。

CREATE OR REPLACE PROCEDURE display_users (
    pi_date1          IN DATE,
    pi_date2          IN DATE,
    po_userdisp_cur   OUT SYS_REFCURSOR 
)
    IS
BEGIN
    OPEN po_userdisp_cur FOR SELECT u.enrollno,
                                    u.error_code,
                                    u.enroll_date
                             FROM user_table u
                             WHERE u.enroll_date BETWEEN pi_date1 AND pi_date2;
END;

这可以很容易地在 java 中使用来获取记录,如下所示:

Using oracle ref cursors in java

【讨论】:

【参考方案2】:

如果您只是想将它输出到屏幕上,您可以在循环的每次迭代中使用 dbms_output.put_line,并确保在运行代码时在您的环境中“设置 serveroutput on”。如果您愿意,还可以将它们连接成每行一行输出。

dbms_output.put_line('Enrolled No: ' || to_char(po_enrollno));
dbms_output.put_line('Error Code: ' || po_error_code);
dbms_output.put_line('Enrolled Date: ' || to_char(po_enroll_date));

如果您想收集数据以供以后使用,那么您需要将记录插入到您创建的新表中。我们将其称为临时表,您需要确保在开始之前删除其中的所有记录。

insert into my_temp_table values( po_enrollno, po_error_code, po_enroll_date);

【讨论】:

对不起,我忘了说我实际上打算从 Java 代码中调用这个过程,并将结果分配到某种容器中。我正在通过 PL/SQL Developer 中的测试窗口检查结果。而且我不允许将表插入数据库(我应该提到这些对不起)。有没有其他方法可以做到这一点?谢谢 在 Java 中创建一个数组并将结果保存在内存中?尽管您可能会遇到性能问题,具体取决于您打算检索多少条记录

以上是关于如何在 pl/sql 过程中使用游标返回多行和多列?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 ref 游标是不是从 pl/sql 过程返回数据

如何将游标添加到 PL/SQL 块中的过程中?

PL/SQL 打印出存储过程返回的引用游标

oracle游标的使用

Oracle 游标简介

Oracle Pl/sql 从多个查询中返回一个游标