Can I pass an explicit cursor to a function/procedure for use in FOR loop?

后端 未结 4 1112
时光说笑
时光说笑 2021-01-12 02:59

I have a procedure that performs some calculations on all records returned by a cursor. It looks a bit like this:

PROCEDURE do_calc(id table.id_column%TYPE)
         


        
相关标签:
4条回答
  • 2021-01-12 03:54

    Yes you can use Cursor explicitly into procedure and function,for that cursor need to declare into package as variable

    0 讨论(0)
  • 2021-01-12 03:55

    Create a package.

    Declare your cursor as package variable.

    Use %rowtype to set function parameter type.

    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;
    
    0 讨论(0)
  • 2021-01-12 04:03

    Try this one, 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;
    
    0 讨论(0)
  • 2021-01-12 04:05

    I had a similar problem, where I had two cursors that needed to be processed the same way, so this is how I figured it out.

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

    You can also use this if you want to bulk collect your cursors. You just need to change your helper procedure process_emp_cv; the rest can stay the same.

    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;
    
    0 讨论(0)
提交回复
热议问题