Вопрос по – Могу ли я передать явный курсор в функцию / процедуру для использования в цикле FOR?

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 синтаксис и неявный тип записи.

Error: User Rate Limit Exceededif...thenError: User Rate Limit Exceededwilliamrobertson.net/documents/refcursor-to-csv.shtmlError: User Rate Limit Exceeded William Robertson

Ваш Ответ

4   ответа
11

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded

Error: User Rate Limit Exceeded%rowtypeError: User Rate Limit Exceeded

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;
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded David Sykes
Error: User Rate Limit Exceeded
0

Error: User Rate Limit Exceeded

    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;
1

Error: User Rate Limit Exceeded

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;
/

Error: User Rate Limit Exceededbulk collectError: User Rate Limit Exceededprocess_emp_cvError: User Rate Limit Exceeded

Using BULK COLLECT

 --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;
-1

Похожие вопросы