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

后端 未结 4 1144
时光说笑
时光说笑 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 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;
    

提交回复
热议问题