【问题标题】:How to return multiple rows from the stored procedure? (Oracle PL/SQL)如何从存储过程中返回多行? (甲骨文 PL/SQL)
【发布时间】:2010-09-11 04:34:36
【问题描述】:

我想创建一个带有一个参数的存储过程,它将根据参数返回不同的记录集。这样做的方法是什么?我可以从普通 SQL 调用它吗?

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    以下是如何构建一个返回结果集的函数,该结果集可以像表格一样进行查询:

    SQL> create type emp_obj is object (empno number, ename varchar2(10));
      2  /
    
    Type created.
    
    SQL> create type emp_tab is table of emp_obj;
      2  /
    
    Type created.
    
    SQL> create or replace function all_emps return emp_tab
      2  is
      3     l_emp_tab emp_tab := emp_tab();
      4     n integer := 0;
      5  begin
      6     for r in (select empno, ename from emp)
      7     loop
      8        l_emp_tab.extend;
      9        n := n + 1;
     10       l_emp_tab(n) := emp_obj(r.empno, r.ename);
     11     end loop;
     12     return l_emp_tab;
     13  end;
     14  /
    
    Function created.
    
    SQL> select * from table (all_emps);
    
         EMPNO ENAME
    ---------- ----------
          7369 SMITH
          7499 ALLEN
          7521 WARD
          7566 JONES
          7654 MARTIN
          7698 BLAKE
          7782 CLARK
          7788 SCOTT
          7839 KING
          7844 TURNER
          7902 FORD
          7934 MILLER
    

    【讨论】:

    • 我认为这需要 10g,但这是最优雅的解决方案。 (我讨厌引用游标)。
    • 这不是优雅的解决方案,因为您需要为具有不同列的所有表创建类型
    【解决方案2】:

    我想你想返回一个 REFCURSOR:

    create function test_cursor 
                return sys_refcursor
                is
                        c_result sys_refcursor;
                begin
                        open c_result for
                        select * from dual;
                        return c_result;
                end;
    

    更新:如果您需要从 SQL 调用它,请使用 @Tony Andrews 建议的表函数。

    【讨论】:

    • 我想使用这样的东西,因为我事先不知道我的领域。但是select * from test_cursor 给出了“尝试访问类型未知的项目的行......”
    【解决方案3】:

    您可以使用 Oracle 流水线函数

    基本上,当您希望 PLSQL(或 java 或 c)例程成为«源»时 数据 - 而不是表 - 您将使用流水线函数。

    简单示例 - 生成一些随机数据
    如何根据输入参数创建 N 个唯一随机数?

    create type array
    as table of number;
    
    
    create function  gen_numbers(n in number default null)
    return array
    PIPELINED
    as
    begin
      for i in 1 .. nvl(n,999999999)
      loop
         pipe row(i);
     end loop;
     return;
    end;
    

    假设我们需要三行来做某事。我们现在可以通过以下两种方式之一做到这一点:

    select * from TABLE(gen_numbers(3));
    

    COLUMN_VALUE


           1
           2
           3
    

    select * from TABLE(gen_numbers)
     where rownum <= 3;
    

    COLUMN_VALUE


           1
           2
           3
    

    pipelied Functions1 pipelied Functions2

    【讨论】:

    • +1 我认为在大多数情况下这是合适的解决方案。与 Tony Andrews 的解决方案相比,它不会提前创建所有行并且需要更少的内存。
    • 我将投票从 1 增加到 2,并且赞成票显示在我的浏览器中
    【解决方案4】:

    如果您想在纯 SQL 中使用它,我会让存储过程用结果行填充表或临时表(或使用@Tony Andrews 方法)。
    如果要使用@Thilo 的解决方案,则必须使用 PL/SQL 循环游标。 这里是一个例子:(我使用了一个过程而不是一个函数,就像@Thilo 所做的那样)

    create or replace procedure myprocedure(retval in out sys_refcursor) is
    begin
      open retval for
        select TABLE_NAME from user_tables;
    end myprocedure;
    
     declare 
       myrefcur sys_refcursor;
       tablename user_tables.TABLE_NAME%type;
     begin
       myprocedure(myrefcur);
       loop
         fetch myrefcur into tablename;
         exit when myrefcur%notfound;
         dbms_output.put_line(tablename);
       end loop;
       close myrefcur;
     end;
    

    【讨论】:

    • notfound 之后的分号是根据Daniel 的评论(作为答案发布)添加的。
    【解决方案5】:
    create procedure <procedure_name>(p_cur out sys_refcursor) as begin open p_cur for select * from <table_name> end;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      • 2018-03-23
      • 2022-01-21
      • 1970-01-01
      • 2015-09-20
      • 2020-04-24
      • 2012-01-28
      相关资源
      最近更新 更多