Почему мы не можем использовать сильный курсор ref с динамическим оператором SQL? - PullRequest
2 голосов
/ 06 мая 2010

Я пытаюсь использовать сильную ссылку с динамической SQL-статистикой, но выдает ошибку, но когда я использую слабый курсор, это работает, пожалуйста, объясните, в чем причина, и пожалуйста перешлите мне любую ссылку на архитектуру сервера Oracle, содержащую информацию о том, как выполняется компиляция и анализ на сервере Oracle. Это ошибка вместе с кодом.

ERROR at line 6:
ORA-06550: line 6, column 7:
PLS-00455: cursor 'EMP_REF_CUR' cannot be used in dynamic SQL OPEN statement
ORA-06550: line 6, column 2:
PL/SQL: Statement ignored

declare
      type ref_cur_type IS REF CURSOR RETURN employees%ROWTYPE; --Creating a strong REF cursor,employees is a table
     emp_ref_cur ref_cur_type;
     emp_rec employees%ROWTYPE;
BEGIN      
   OPEN emp_ref_cur FOR 'SELECT * FROM employees';
           LOOP
                   FETCH emp_ref_cur INTO emp_rec;
                   EXIT WHEN emp_ref_cur%NOTFOUND;
           END lOOP;       
END;

Ответы [ 3 ]

9 голосов
/ 06 мая 2010

Вот процедура со строго типизированным ref-курсором:

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select * from dept;
  7  end;
  8  /

Procedure created.

SQL>

Следующий оператор не выполняется, поскольку подпись записи EMP не совпадает с подписью таблицы DEPT.

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select * from emp;
  7  end;
  8  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE P1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/5      PL/SQL: SQL Statement ignored
6/9      PLS-00382: expression is of wrong type

SQL>

Но если мы изменим проекцию, чтобы она соответствовала таблице DEPT, мы снова добьемся успеха:

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          select deptno, ename, job from emp;
  7  end;
  8  /

Procedure created.

SQL>

Итак, почему мы не можем использовать строго типизированный ref-курсор с динамическим SQL?

SQL> create or replace procedure p1 is
  2      type dept_rc is ref cursor return dept%rowtype;
  3      my_ref_cursor dept_rc;
  4  begin
  5      open my_ref_cursor for
  6          'select * from dept';
  7  end;
  8  /

Warning: Procedure created with compilation errors.

SQL> show error
Errors for PROCEDURE P1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
5/5      PL/SQL: Statement ignored
5/10     PLS-00455: cursor 'MY_REF_CURSOR' cannot be used in dynamic SQL
         OPEN statement

SQL>

Поскольку компилятор не может проанализировать строку в динамическом операторе SQL. Поэтому он не может утверждать, что столбцы в проекции запроса совпадают по числу и типу данных подписи курсора ссылки. Следовательно, он не может проверить контракт между переменной курсора ref и запросом. Еще проще понять, почему это нельзя допустить, если учесть, что динамический оператор SQL может быть собран из запроса на USER_TAB_COLUMNS.

1 голос
/ 23 января 2013

Другая возможность - объявить и определить объект типа записи в качестве контейнера для результатов запроса. Это может быть полезно, если запрос является запросом JOIN, возвращающим столбцы из нескольких соединенных таблиц.

SQL> create or replace procedure p1 is
     /* Declare you destination data structure row container */
     TYPE TestRecTyp IS RECORD (
        deptno varchar(50),
        ename  varchar(50),
        job    varchar(50)
     );
     /* Define an instance of the record type */
     testrec TestRecTyp;

     type dept_rc is ref cursor; /*return dept%rowtype;*/
     my_ref_cursor dept_rc;
     begin
         open my_ref_cursor for 'select deptno,ename,job from emp';
         LOOP
             FETCH my_ref_cursor INTO testrec;
         EXIT WHEN my_ref_cursor%NOTFOUND;

             /* Do some operations with testrec*/

         END LOOP;
     end;

ПРИМЕЧАНИЕ. Вы можете использовать описанную выше технику в динамически построенном операторе SQL-запроса, заменив 'select deptno, ename, job from emp' на переменную, такую ​​как v_sql, и обновите эту переменную с помощью оператора SQL в теле процедуры .

0 голосов
/ 19 марта 2018

Вам не разрешается открывать строго типизированный ref-курсор для динамического sql, поскольку движок оракула не может проверить, соответствует ли структура динамического sql структуре возвращаемого типа ref-курсора.

...