9

我有一个对游标返回的所有记录执行一些计算的过程。它看起来有点像这样:

PROCEDURE do_calc(id table.id_column%TYPE)
IS
  CURSOR c IS
    SELECT col1, col2, col3
      FROM table
     WHERE ...;
BEGIN
  FOR r IN c LOOP
    -- do some complicated calculations using r.col1, r.col2, r.col3 etc.
  END LOOP;
END;

现在,我需要对来自不同表的不同记录集执行完全相同的计算。但是,它们具有与上述示例相同的“形状”。

是否可以编写如下所示的过程:

PROCEDURE do_calc2(c some_cursor_type)
IS
BEGIN
  FOR r IN c LOOP
    -- do the calc, knowing we have r.col1, r.col2, r.col3, etc.
  END LOOP;
END;

我知道SYS_REFCURSOR,但我想知道是否可以使用更方便的FOR ... LOOP语法和隐式记录类型。

4

4 回答 4

12

创建一个包。

将光标声明为包变量。

用于%rowtype设置函数参数类型。

create or replace package test is
  cursor c is select 1 as one, 2 as two from dual;

  procedure test1;
  function test2(test_record c%ROWTYPE) return number;

end test;


create or replace package body test is
  procedure test1 is    
  begin
    for r in c loop      
      dbms_output.put_line(test2(r));
    end loop;
  end;

  function test2(test_record c%ROWTYPE) return number is
    l_summ number;
  begin
    l_summ := test_record.one + test_record.two;
    return l_summ;
  end;
end test;
于 2012-05-18T06:39:30.867 回答
4

我有一个类似的问题,我有两个需要以相同方式处理的游标,所以这就是我想出来的。

DECLARE
   --Define our own rowType
   TYPE employeeRowType IS RECORD (
      f_name           VARCHAR2(30),
      l_name            VARCHAR2(30));
   --Define our ref cursor type
   --If we didn't need our own rowType, we could have this: RETURN employees%ROWTYPE
   TYPE empcurtyp IS REF CURSOR RETURN employeeRowType;

   --Processes the cursors
   PROCEDURE process_emp_cv (emp_cv IN empcurtyp) IS
      person employeeRowType;
   BEGIN
      LOOP
         FETCH emp_cv INTO person;
         EXIT WHEN emp_cv%NOTFOUND;
         DBMS_OUTPUT.PUT_LINE('Name = ' || person.f_name ||
                          ' ' || person.l_name);
      END LOOP;
   END;

   --Defines the cursors
   PROCEDURE mainProcedure IS
    emp empcurtyp;
   BEGIN
      OPEN emp FOR SELECT first_name, last_name FROM employees WHERE salary > 50000;
      process_emp_cv(emp);
      CLOSE emp;

      OPEN emp FOR SELECT first_name, last_name FROM kuren WHERE first_name LIKE 'J%';
      process_emp_cv(emp);
      CLOSE emp;
   END;

BEGIN
  mainProcedure;
END;
/

如果您想批量收集游标,也可以使用它。你只需要改变你的助手程序process_emp_cv;其余的可以保持不变。

使用批量收集

 --Processes the cursors
   PROCEDURE process_emp_cv (emp_cv IN empcurtyp) IS
      TYPE t_employeeRowTable IS TABLE OF employeeRowType;
      employeeTable   t_employeeRowTable;
   BEGIN
      LOOP
         FETCH emp_cv BULK COLLECT INTO employeeTable LIMIT 50;
         FOR indx IN 1 .. employeeTable.Count
         LOOP
            DBMS_OUTPUT.PUT_LINE('Name = ' || employeeTable(indx).f_name ||
                          ' ' || employeeTable(indx).l_name);
         END LOOP;
         EXIT WHEN emp_cv%NOTFOUND;
      END LOOP;
   END;
于 2018-03-13T16:11:52.230 回答
0

试试这个,Usong ref cursor。

    declare
    type c is ref cursor;
    c2 c;
    type rec is record(
    id number,
    name varchar(20)
    );
    r rec;
    procedure p1(c1 in out c,r1 in out rec)is begin

    loop
    fetch c1 into r1;
    exit when c1%notfound;
    dbms_output.put_line(r1.id || ' ' ||r1.name);
    end loop;
    end;
    begin
    open c2 for select id, name from student;
    p1(c2,r);
    end;
于 2018-05-07T04:13:00.237 回答
-1

是的,您可以在过程和函数中显式使用游标,因为该游标需要在包中声明为变量

于 2015-05-07T08:30:59.730 回答