2010-05-06 44 views
2

我想用动态sql语句强大的引用当然,但它给出了一个错误,但是当我使用弱游标它的作品,请解释是什么原因,请 转发我的任何链接的Oracle服务器架构师有关Oracle服务器如何完成编译和解析的问题。这是代码错误。为什么我们不能在动态SQL语句中使用强引用?

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; 

回答

8

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

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语句中的字符串。所以它不能断言查询投影中的列与数字匹配并且数据类型是引用游标的签名。因此它无法验证引用游标变量和查询之间的契约。当我们认为动态SQL语句可以从USER_TAB_COLUMNS上的一个查询中组合出来时,为什么不能这么做呢?

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查询语句“选择DEPTNO,为ename,从EMP工作”,与诸如v_sql一个变量,并用内SQL语句更新该变量程序的主体。

相关问题