3

我正在尝试使用带有动态 sql 语句的强 ref cur,但它给出了一个错误,但是当我使用弱游标时它可以工作,请解释原因并请转发我任何包含有关如何操作的 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;
4

3 回答 3

9

这是一个带有强类型引用游标的过程:

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>

那么,为什么我们不能在动态 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 上的查询中组装时,更容易理解为什么不允许这样做。

于 2010-05-06T19:21:20.187 回答
1

另一种可能性是声明并定义一个记录类型对象作为查询结果的容器。如果查询是 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 语句更新此变量。

于 2013-01-22T22:32:02.247 回答
1

不允许为动态 sql 打开强类型引用游标,因为 oracle 引擎无法检查动态 sql 的结构是否与引用游标的返回类型匹配。

于 2018-03-19T06:22:51.573 回答