[oracle] How to use a variable from a cursor in the select statement of another cursor in pl/sql

I want to run a query, get the results and then iterate through the results of that query with another select statement using the values of the first statement in my 2nd statement (cursor).

I have 40 users in my db. All the users have the same db schema structure. I want to get the username via :

SELECT  distinct username 
   from all_users 

then use the user name to run a query like this:

Select lastname, firstname, email, email2 from username.member.

My results set will return multiple rows so I need a row type as well.

I have tried many different pl/sql combinations:

DECLARE
   CURSOR client_cur IS
   SELECT  distinct username 
   from all_users 
   where length(username) = 3;
   -- client cursor 
   CURSOR emails_cur (cli all_users.username%TYPE) IS
   SELECT id, name 
     FROM cli.org;
BEGIN
   FOR client IN client_cur LOOP
      dbms_output.put_line('Client is '|| client.username);
      FOR email_rec in client_cur(client.username) LOOP
         dbms_output.put_line('Org id is ' ||email_rec.id || ' org nam ' || email_rec.name);
      END LOOP;
  END LOOP;
END;
/

and

DECLARE
  CURSOR c1 IS
    SELECT  distinct username from all_users where length(username) = 3;
    client c1%rowtype;
   cursor c2 is Select id, name, allow_digest_flg from c1.username.org;
 digest c2%rowtype;
-- declare record variable that represents a row fetched from the employees table
--   employee_rec c1%ROWTYPE; 
 BEGIN
-- open the explicit cursor and use it to fetch data into employee_rec
    OPEN c1;
  loop
     FETCH c1 INTO client; 
   open c2; 
   loop
    fetch c2 into digest;
      DBMS_OUTPUT.PUT_LINE('digest is : ' || c2.id || ' and name is ' || c2.name || ' flg is ' || c2.allow_digest_flg );
   end loop;
  end loop;
 END;
/

AND MANY VARIATIONS OF THESE.

Can someone help me. THANKS

This question is related to oracle plsql

The answer is


Use alter session set current_schema = <username>, in your case as an execute immediate.

See Oracle's documentation for further information.

In your case, that would probably boil down to (untested)

DECLARE

   CURSOR client_cur IS
     SELECT  distinct username 
       from all_users 
      where length(username) = 3;

   -- client cursor 
   CURSOR emails_cur IS
   SELECT id, name 
     FROM org;

BEGIN

   FOR client IN client_cur LOOP

   -- ****
      execute immediate 
     'alter session set current_schema = ' || client.username;
   -- ****

      FOR email_rec in client_cur LOOP

         dbms_output.put_line(
             'Org id is ' || email_rec.id || 
             ' org nam '  || email_rec.name);

      END LOOP;

  END LOOP;
END;
/

You can certainly do something like

SQL> ed
Wrote file afiedt.buf

  1  begin
  2    for d in (select * from dept)
  3    loop
  4      for e in (select * from emp where deptno=d.deptno)
  5      loop
  6        dbms_output.put_line( 'Employee ' || e.ename ||
  7                              ' in department ' || d.dname );
  8      end loop;
  9    end loop;
 10* end;
SQL> /
Employee CLARK in department ACCOUNTING
Employee KING in department ACCOUNTING
Employee MILLER in department ACCOUNTING
Employee smith in department RESEARCH
Employee JONES in department RESEARCH
Employee SCOTT in department RESEARCH
Employee ADAMS in department RESEARCH
Employee FORD in department RESEARCH
Employee ALLEN in department SALES
Employee WARD in department SALES
Employee MARTIN in department SALES
Employee BLAKE in department SALES
Employee TURNER in department SALES
Employee JAMES in department SALES

PL/SQL procedure successfully completed.

Or something equivalent using explicit cursors.

SQL> ed
Wrote file afiedt.buf

  1  declare
  2    cursor dept_cur
  3        is select *
  4             from dept;
  5    d dept_cur%rowtype;
  6    cursor emp_cur( p_deptno IN dept.deptno%type )
  7        is select *
  8             from emp
  9            where deptno = p_deptno;
 10    e emp_cur%rowtype;
 11  begin
 12    open dept_cur;
 13    loop
 14      fetch dept_cur into d;
 15      exit when dept_cur%notfound;
 16      open emp_cur( d.deptno );
 17      loop
 18        fetch emp_cur into e;
 19        exit when emp_cur%notfound;
 20        dbms_output.put_line( 'Employee ' || e.ename ||
 21                              ' in department ' || d.dname );
 22      end loop;
 23      close emp_cur;
 24    end loop;
 25    close dept_cur;
 26* end;
 27  /
Employee CLARK in department ACCOUNTING
Employee KING in department ACCOUNTING
Employee MILLER in department ACCOUNTING
Employee smith in department RESEARCH
Employee JONES in department RESEARCH
Employee SCOTT in department RESEARCH
Employee ADAMS in department RESEARCH
Employee FORD in department RESEARCH
Employee ALLEN in department SALES
Employee WARD in department SALES
Employee MARTIN in department SALES
Employee BLAKE in department SALES
Employee TURNER in department SALES
Employee JAMES in department SALES

PL/SQL procedure successfully completed.

However, if you find yourself using nested cursor FOR loops, it is almost always more efficient to let the database join the two results for you. After all, relational databases are really, really good at joining. I'm guessing here at what your tables look like and how they relate based on the code you posted but something along the lines of

FOR x IN (SELECT *
            FROM all_users,
                 org
           WHERE length(all_users.username) = 3
             AND all_users.username = org.username )
LOOP
  <<do something>>
END LOOP;