【问题标题】:Get resultset from oracle stored procedure从 oracle 存储过程中获取结果集
【发布时间】:2010-11-13 07:43:23
【问题描述】:

我正在将存储过程从 SQL Server 转换为 Oracle。 此存储过程提供直接结果集。我的意思是,如果您在例如 Management Studio 中调用存储过程,您将直接获得结果集。

通过转换为 Oracle,我遇到了我在 Oracle 中不会显示结果集的问题

我在网上搜索,发现存储过程应该产生一个 REF CURSOR,但我仍然带着问题写了一小段代码来获取结果集并处理它。

伪代码:

调用存储过程并获取游标 用那个光标做一些事情,这样我的结果集就会出现

有人出主意吗?

【问题讨论】:

  • 我是伤员。这个问题的浏览量 > 90K,只有 20 人赞成。每次观看都值得投票。 :D
  • @Dr.MAF 这个问题现在有近 110,000 次浏览。如果你问我,那就太令人惊讶了。
  • @Wilson 对不起,我没明白你的意思。我要问你什么?

标签: oracle stored-procedures plsql


【解决方案1】:
CREATE OR REPLACE PROCEDURE SP_Invoices(p_nameClient IN CHAR)
AS
BEGIN       
    FOR c_invoice IN 
    (
       SELECT CodeInvoice, NameClient FROM Invoice
       WHERE NameClient = p_nameClient
    )
    LOOP
        dbms_output.put_line('Code Invoice: ' || c_invoice.CodeInvoice);
        dbms_output.put_line('Name Client : ' ||  c_invoice.NameClient );
    END LOOP;
END;

在 SQL Developer 中执行:

BEGIN
    SP_Invoices('Perico de los palotes');
END;
-- Or:
EXEC SP_Invoices('Perico de los palotes');

输出:

> Code Invoice: 1 
> Name Client : Perico de los palotes
> Code Invoice: 2 
> Name Client : Perico de los palotes

【讨论】:

    【解决方案2】:

    仅供参考,从 Oracle 12c 开始,您可以这样做:

    CREATE OR REPLACE PROCEDURE testproc(n number)
    AS
      cur SYS_REFCURSOR;
    BEGIN
        OPEN cur FOR SELECT object_id,object_name from all_objects where rownum < n;
        DBMS_SQL.RETURN_RESULT(cur);
    END;
    /
    
    EXEC testproc(3);
    
    OBJECT_ID OBJECT_NAME                                                                                                                     
    ---------- ------------
    100 ORA$BASE                                                                                                                        
    116 DUAL                                                                                                                            
    

    这应该更接近其他数据库,并简化迁移。 但这对我来说并不完美,例如 SQL 开发人员无法将其作为普通 SELECT 很好地显示。

    我更喜欢管道函数的输出,但它们需要更多样板代码。

    更多信息: https://oracle-base.com/articles/12c/implicit-statement-results-12cr1

    【讨论】:

    • @Ejrr1085 你是否使用了“运行脚本”(F5)。为我工作。我不必执行通常的“设置服务器输出”,但您也可以试试这个。
    【解决方案3】:

    我的解决方案是创建一个流水线函数。优点是查询可以是一行:

    • select * from table(yourfunction(param1, param2));
    • 您可以将您的结果加入到其他表格中,或者根据需要对它们进行过滤或排序..
    • 结果显示为常规查询结果,因此您可以轻松操作它们。

    要定义函数,您需要执行以下操作:

      -- Declare the record columns
      TYPE your_record IS RECORD(
         my_col1 VARCHAR2(50), 
         my_col2 varchar2(4000)
      );
      TYPE your_results IS TABLE OF your_record;
    
      -- Declare the function
      function yourfunction(a_Param1 varchar2, a_Param2 varchar2)
      return your_results pipelined is
        rt          your_results;
      begin
        -- Your query to load the table type
        select s.col1,s.col2
        bulk collect into rt
        from your_table s
        where lower(s.col1) like lower('%'||a_Param1||'%');
    
        -- Stuff the results into the pipeline..
        if rt.count > 0 then 
          for i in rt.FIRST .. rt.LAST loop 
            pipe row (rt(i)); 
          end loop; 
        end if;
    
        -- Add more results as you please....
        return;
      end find;
    

    如上所述,查看结果所需要做的就是:

    select * from table(yourfunction(param1, param2)) t order by t.my_col1;
    

    【讨论】:

    • 这个解决方案优于公认的解决方案的好处是,返回的结果就像任何常规选择语句一样,这意味着您的调用代码在填充某种数据结构时不需要做任何不同的事情,比如表或数组(这是您 99% 的时间需要做的,以便您可以在调用代码中进行进一步处理)。使用公认的解决方案会打印结果,因此调用代码需要解析打印结果以将数据转换为某种非常容易出错的数据结构。
    【解决方案4】:

    Oracle 不是 sql server。在 SQL Developer 中尝试以下操作

    variable rc refcursor;
    exec testproc(:rc2);
    print rc2
    

    【讨论】:

      【解决方案5】:

      您好,我知道这是不久前有人问过的,但我刚刚弄清楚了,它可能对其他人有所帮助。不确定这是否正是您要查找的内容,但这是我调用存储过程并使用 SQL Developer 查看输出的方式。
      在 SQL Developer 中查看 proc 时,右键单击并选择“运行”或选择 Ctrl+F11 以打开运行 PL/SQL 窗口。这将创建一个包含您需要修改的输入和输出参数的模板。我的过程返回一个 sys_refcursor。对我来说,棘手的部分是声明一个与 proc 返回的 select stmt / sys_refcursor 完全相同的行类型:

      DECLARE
        P_CAE_SEC_ID_N NUMBER;
        P_FM_SEC_CODE_C VARCHAR2(200);
        P_PAGE_INDEX NUMBER;
        P_PAGE_SIZE NUMBER;
        v_Return sys_refcursor;
        type t_row is record (CAE_SEC_ID NUMBER,FM_SEC_CODE VARCHAR2(7),rownum number, v_total_count number);
        v_rec t_row;
      
      BEGIN
        P_CAE_SEC_ID_N := NULL;
        P_FM_SEC_CODE_C := NULL;
        P_PAGE_INDEX := 0;
        P_PAGE_SIZE := 25;
      
        CAE_FOF_SECURITY_PKG.GET_LIST_FOF_SECURITY(
          P_CAE_SEC_ID_N => P_CAE_SEC_ID_N,
          P_FM_SEC_CODE_C => P_FM_SEC_CODE_C,
          P_PAGE_INDEX => P_PAGE_INDEX,
          P_PAGE_SIZE => P_PAGE_SIZE,
          P_FOF_SEC_REFCUR => v_Return
        );
        -- Modify the code to output the variable
        -- DBMS_OUTPUT.PUT_LINE('P_FOF_SEC_REFCUR = ');
        loop
          fetch v_Return into v_rec;
          exit when v_Return%notfound;
          DBMS_OUTPUT.PUT_LINE('sec_id = ' || v_rec.CAE_SEC_ID || 'sec code = ' ||v_rec.FM_SEC_CODE);
        end loop;
      
      END;
      

      【讨论】:

        【解决方案6】:

        在 SQL Plus 中:

        SQL> create procedure myproc (prc out sys_refcursor)
          2  is
          3  begin
          4     open prc for select * from emp;
          5  end;
          6  /
        
        Procedure created.
        
        SQL> var rc refcursor
        SQL> execute myproc(:rc)
        
        PL/SQL procedure successfully completed.
        
        SQL> print rc
        
             EMPNO ENAME      JOB              MGR HIREDATE           SAL       COMM     DEPTNO
        ---------- ---------- --------- ---------- ----------- ---------- ---------- ----------
              7839 KING       PRESIDENT            17-NOV-1981       4999                    10
              7698 BLAKE      MANAGER         7839 01-MAY-1981       2849                    30
              7782 CLARKE     MANAGER         7839 09-JUN-1981       2449                    10
              7566 JONES      MANAGER         7839 02-APR-1981       2974                    20
              7788 SCOTT      ANALYST         7566 09-DEC-1982       2999                    20
              7902 FORD       ANALYST         7566 03-DEC-1981       2999                    20
              7369 SMITHY     CLERK           7902 17-DEC-1980       9988         11         20
              7499 ALLEN      SALESMAN        7698 20-FEB-1981       1599       3009         30
              7521 WARDS      SALESMAN        7698 22-FEB-1981       1249        551         30
              7654 MARTIN     SALESMAN        7698 28-SEP-1981       1249       1400         30
              7844 TURNER     SALESMAN        7698 08-SEP-1981       1499          0         30
              7876 ADAMS      CLERK           7788 12-JAN-1983       1099                    20
              7900 JAMES      CLERK           7698 03-DEC-1981        949                    30
              7934 MILLER     CLERK           7782 23-JAN-1982       1299                    10
              6668 Umberto    CLERK           7566 11-JUN-2009      19999          0         10
              9567 ALLBRIGHT  ANALYST         7788 02-JUN-2009      76999         24         10
        

        【讨论】:

        • 太棒了!谢谢你的回答,托尼。我可以通过 Unix/Linux 脚本将这些结果导出到 CSV 吗?
        • print rc 在 sql plus 中很好用,如何在 SQL Developer 的网格中显示 rc?
        • 我是伤员。这个问题的浏览量 > 90K,只有 20 人赞成。每次观看都值得投票。您的答案每次观看都值得 10 票赞成。非常感谢。
        • 我想问上面@Stack0verflow 提出的相同问题。如何以网格格式显示此结果?
        • 我的救星!我在一个类似的问题上被困了 6 个小时。
        【解决方案7】:

        在 SQL Plus 中:

        SQL> var r refcursor
        SQL> set autoprint on
        SQL> exec :r := function_returning_refcursor();
        

        将最后一行替换为对您的过程/函数的调用,然后将显示 refcursor 的内容

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-03-28
          • 1970-01-01
          • 1970-01-01
          • 2012-02-11
          • 2020-02-18
          • 2023-03-28
          • 2011-11-25
          • 2023-04-06
          相关资源
          最近更新 更多