Oracle 是否可以将带有参数的游标作为过程的参数传递?

Oracle 是否可以将带有参数的游标作为过程的参数传递?,oracle,plsql,Oracle,Plsql,我有很多类似的处理方法要做,我想为它编写一个pl/sql脚本。 查看代码比解释代码更容易理解,因此这里是一个简化版本: create or replace package my_test as cursor my_cursor(my_filter NUMBER) is select column1, column2 from mytable where column3 = my_filter; cursor my_cursor2(my_filter VARCHAR2) is select

我有很多类似的处理方法要做,我想为它编写一个pl/sql脚本。 查看代码比解释代码更容易理解,因此这里是一个简化版本:

create or replace package my_test as
  cursor my_cursor(my_filter NUMBER) is select column1, column2 from mytable where column3 = my_filter;
  cursor my_cursor2(my_filter VARCHAR2) is select column1, column2 from mytable where column4 LIKE my_filter;
  -- ...

  procedure test1;
  procedure test2(p_cursor XXX);
  function test3(test_record XXX%ROWTYPE) return number;

end my_test;
/

create or replace package body my_test as
  procedure test1 is    
  begin
    test2(my_cursor(3));
    test2(my_cursor2('foo%'));
    test2(my_cursor(5));
    -- ...
  end test1;

  procedure test2(p_cursor XXX) is
    tmp number;
  begin
    for r in p_cursor loop      
      --some actions 
      tmp := test3(r);
      --some actions
    end loop;
  end test2;

  function test3(test_record XXX%ROWTYPE) return number is
    tmp_sum number;
  begin
    -- ...
    tmp_sum := test_record.column1 + test_record.column2;
    -- ...
    return l_summ;
  end test3;


end my_test;
/

BEGIN
    my_test.test1();
END;
/

我已经尽力了,但没有成功。也许有人能帮我?有可能实现这样的事情吗?我应该放什么来代替XXX呢?

光标变量非常适合您想要做的事情

下面是对部分代码的重写,演示了如何使用它们:

CREATE OR REPLACE PACKAGE my_test
AS
   PROCEDURE test1;

   PROCEDURE test2 (p_cursor IN OUT SYS_REFCURSOR);
END my_test;
/

CREATE OR REPLACE PACKAGE BODY my_test
AS
   FUNCTION my_cursor (my_filter NUMBER)
      RETURN SYS_REFCURSOR
   IS
      l_cursor   SYS_REFCURSOR;
   BEGIN
      OPEN l_cursor FOR
         SELECT column1, column2
           FROM mytable
          WHERE column3 = my_filter;

      RETURN l_cursor;
   END;

   PROCEDURE test1
   IS
   BEGIN
      test2 (my_cursor (3));
      test2 (my_cursor (5));
   END test1;

   PROCEDURE test2 (p_cursor xxx)
   IS
      tmp   NUMBER;
   BEGIN
      LOOP
         FETCH p_cursor INTO tmp;

         EXIT WHEN p_cursor%NOTFOUND;
         --some actions
         NULL;
      END LOOP;

      CLOSE p_cursor;
   END test2;
END my_test;
/
您可以使用OPEN FOR语法将查询(及其结果集)与变量相关联。然后可以使用通常的操作获取、关闭对%游标属性的引用


并在完成后关闭光标。:-)

定义一个记录类型以匹配要执行的查询的投影。您可以使用它来定义
test3()
的IN参数

定义一个返回此记录类型的ref游标。您可以使用它来定义
test2()
的IN参数

不是游标,而是定义返回由该游标类型定义的ref游标的函数

因此,您的软件包如下所示:

create or replace package my_test as

  type t_record is record(
     column1 mytable.column1%type
    ,column2 mytable.column2%type
  );

  type t_cursor is ref cursor return t_record;

  function my_cursor (my_filter NUMBER)   return t_cursor ;
  function my_cursor2(my_filter VARCHAR2) return t_cursor ;

  procedure test1;
  procedure test2(p_cursor t_cursor);
  function  test3(test_record t_record) return number;

end my_test;
/
实现如下所示(通过一些输出使演示更易于理解):

我说的是演示吗?当然有。

不仅有(真正的)快速响应,还有演示。谢谢!
create or replace package body my_test as

  function my_cursor(my_filter NUMBER) return t_cursor is 
      rc sys_refcursor;
  begin
    open rc for  select column1, column2 from mytable where column3 = my_filter;
    return rc;
  end my_cursor;

  function my_cursor2(my_filter VARCHAR2)  return t_cursor is 
      rc sys_refcursor;
  begin
    open rc for  select column1, column2 from mytable where column4 LIKE my_filter;
    return rc;
  end my_cursor2;

  procedure test1 is    
  begin
    dbms_output.put_line('test2(my_cursor, 3)');
    test2(my_cursor(3)); 
    dbms_output.put_line('test2(my_cursor2, foo');
    test2(my_cursor2('foo%'));
    dbms_output.put_line('test2(my_cursor,5)');
    test2(my_cursor(5));
    -- ...
  end test1;

  procedure test2(p_cursor t_cursor) is
    tmp number;
    l_rec t_record;
  begin
    loop
      fetch p_cursor into l_rec;
      exit when p_cursor%notfound;
      --some actions 
      tmp := test3(l_rec);
      dbms_output.put_line(l_rec.column1 ||'+'||l_rec.column2||'='||tmp);
      --some actions
    end loop;
    close p_cursor;
  end test2;

  function test3(test_record t_record) return number is
    tmp_sum number;
  begin
    -- ...
    tmp_sum := test_record.column1 + test_record.column2;
    -- ...
    return tmp_sum;
  end test3;

end my_test;
/