Как использовать переменную из курсора в операторе выбора другого курсора в pl / sql - PullRequest
3 голосов
/ 02 ноября 2010

Я хочу выполнить запрос, получить результаты, а затем перебрать результаты этого запроса с помощью другого оператора select, используя значения первого оператора в моем втором операторе (курсор).

У меня 40 пользователей в моей базе данных. Все пользователи имеют одинаковую структуру схемы БД. Я хочу получить имя пользователя через:

SELECT  distinct username 
   from all_users 

затем используйте имя пользователя для запуска запроса, подобного этому:

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

Мой набор результатов будет возвращать несколько строк, поэтому мне также нужен тип строки.

Я пробовал много разных комбинаций pl / sql:

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

и

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

И МНОГИЕ ИЗМЕНЕНИЯ ЭТИХ.

Может кто-нибудь мне помочь. БЛАГОДАРЯ

Ответы [ 3 ]

6 голосов
/ 02 ноября 2010

Для этого вам нужно использовать динамический SQL;что-то вроде:

DECLARE
    TYPE cur_type IS REF CURSOR;

    CURSOR client_cur IS
        SELECT DISTING username
        FROM all_users
        WHERE length(username) = 3;

    emails_cur cur_type;
    l_cur_string VARCHAR2(128);
    l_email_id <type>;
    l_name <type>;
BEGIN
    FOR client IN client_cur LOOP
        dbms_output.put_line('Client is '|| client.username);
        l_cur_string := 'SELECT id, name FROM '
            || client.username || '.org';
        OPEN emails_cur FOR l_cur_string;
        LOOP
            FETCH emails_cur INTO l_email_id, l_name;
            EXIT WHEN emails_cur%NOTFOUND;
            dbms_output.put_line('Org id is ' || l_email_id
                || ' org name ' || l_name);
        END LOOP;
        CLOSE emails_cur;
    END LOOP;
END;
/

Отредактировано для исправления двух ошибок и добавления ссылок на документацию 10g для OPEN-FOR и пример , Отредактировано , чтобы сделать внутренний запрос курсора строковой переменной.

4 голосов
/ 02 ноября 2010

Вы, конечно, можете сделать что-то вроде

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.

или что-то эквивалентное, используя явные курсоры.

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.

Однако, если вы обнаружите, что используете циклы FOR с вложенными курсорами, это почти всегдаболее эффективно позволить базе данных объединить два результата для вас.В конце концов, реляционные базы данных действительно очень хороши для объединения.Здесь я предполагаю, как выглядят ваши таблицы и как они соотносятся с кодом, который вы выложили, но что-то вроде

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;
1 голос
/ 29 апреля 2013

Используйте alter session set current_schema = <username>, в вашем случае, как немедленное выполнение.

См. Документация Oracle для получения дополнительной информации.

В вашем случае это, вероятно, сводитсядо ( не проверено )

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;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...