PL/SQL 打印存储过程返回的 ref cursor

38

我该如何从一个存储过程返回的 ref cursor(OUT 变量)中获取数据,并在 SQL*PLUS 中将结果行打印到 STDOUT?

ORACLE 存储过程:

PROCEDURE GetGrantListByPI(p_firstname IN VARCHAR2, p_lastname IN VARCHAR2,
p_orderby IN VARCHAR2, p_cursor OUT grantcur);

PL/SQL:

SET SERVEROUTPUT ON;

DECLARE
  TYPE r_cursor IS REF CURSOR;
  refCursor r_cursor;

  CURSOR grantCursor IS
    SELECT last_name, first_name
    FROM ten_year_pis
    WHERE year_added = 2010;

  last_name VARCHAR2(100);
  first_name VARCHAR2(100);

BEGIN
  OPEN grantCursor;
  FETCH grantCursor INTO last_name, first_name;

  WHILE grantCursor%FOUND LOOP
    PMAWEB_PKG.GetGrantListByPI(last_name, first_name, 'last_name', refCursor);

    --HOW DO I LOOP THROUGH THE RETURNED REF CURSOR (refCursor)
    --AND PRINT THE RESULTING ROWS TO STDOUT?

    FETCH grantCursor into last_name, first_name;
  END LOOP;
  CLOSE grantCursor;
END;
/
5个回答

43

注意:此代码未经测试

为您的refCursor返回类型定义一个记录,称其为rec。例如:

TYPE MyRec IS RECORD (col1 VARCHAR2(10), col2 VARCHAR2(20), ...);  --define the record
rec MyRec;        -- instantiate the record

一旦你从存储过程中获取了refcursor,你可以在现有评论所在的位置添加以下代码:

LOOP
  FETCH refCursor INTO rec;
  EXIT WHEN refCursor%NOTFOUND;
  dbms_output.put_line(rec.col1||','||rec.col2||','||...);
END LOOP;

问题在于存储过程返回一个由两个表连接而成的游标作为结果。我该如何引用连接表的返回类型? - elpisu
3
为了理解光标中的类型和大小,你需要知道其中包含什么。定义一个带有连接字段的记录,并将行获取到该记录中。 - DCookie
谢谢@DCookie,但如果我只需要读取每行的一列,那我该怎么办?我需要创建整个结构吗? - शेखर
您必须创建记录类型以反映您选择的数据。 - DCookie
请注意,在 SQL Developer 中声明之前,需要添加以下行:SET SERVEROUTPUT ON。 - Shilan

19

您可以在SQLPlus级别使用绑定变量来实现这一点。当然,您对输出的格式几乎没有控制。

VAR x REFCURSOR;
EXEC GetGrantListByPI(args, :x);
PRINT x;

你知道我怎么样在一个存储过程中应用同样的逻辑吗?我需要它用于ETL工具(Pentaho Data Integration)。 - Yorfrank Bastidas
1
@YorfrankBastidas,你看过上面的答案了吗 - https://dev59.com/82025IYBdhLWcg3wvIq2#5822771?它讨论了在PL / SQL代码中使用refcursor。 - Dave Costa

7
如果您想要打印select子句中的所有列,可以使用autoprint命令。
CREATE OR REPLACE PROCEDURE sps_detail_dtest(v_refcur OUT sys_refcursor)
AS
BEGIN
  OPEN v_refcur FOR 'select * from dummy_table';
END;

SET autoprint on;

--calling the procedure
VAR vcur refcursor;
DECLARE 
BEGIN
  sps_detail_dtest(vrefcur=>:vcur);
END;

希望这能给你提供一个替代方案。

5
更简单的方法是使用DBMS_SQL.return_result()函数;
假设您的包/过程/游标规范如下:
    create or replace PACKAGE my_package IS
    
    TYPE my_ref_cursor_type IS REF CURSOR;
    
    PROCEDURE my_procedure (
        p_in_param1     IN     VARCHAR2, 
        p_in_param2     IN     VARCHAR2, 
        p_in_param3     IN     VARCHAR2, 
        p_my_ref_cursor OUT    my_ref_cursor_type,
        p_err_code      OUT    NUMBER,
        p_err_msg       OUT    VARCHAR2   
        );
    
    END my_package;

尝试从SQL开发者工作区调用该过程。
SET SERVEROUTPUT ON;

DECLARE

  P_MY_REF_CURSOR my_schema.my_package.my_ref_cursor_type;
  P_ERR_CODE NUMBER;
  P_ERR_MSG VARCHAR2(200);
  
BEGIN

  my_package.my_procedure(
    'VALUE1',
    'VALUE2',
    'VALUE3',
    P_MY_REF_CURSOR => P_MY_REF_CURSOR,
    P_ERR_CODE => P_ERR_CODE,
    P_ERR_MSG => P_ERR_MSG
  );
    DBMS_OUTPUT.PUT_LINE(P_ERR_MSG); 
    DBMS_OUTPUT.PUT_LINE(P_ERR_CODE); 
    DBMS_SQL.return_result(P_MY_REF_CURSOR);

END;

希望这有所帮助!

0

有许多方法可以显示sys_refcursor结果集,其中一个非常简单的方法是使用SQL Developer来提取sys_refcursor并打印输出,步骤如下:

  1. 创建一个测试函数以打印其结果
  2. 执行该函数
  3. 查看输出
  4. 验证结果集

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接