【问题标题】:ORACLE: Cursor with dynamic query - throws error "invalid identifier" for cursor fieldORACLE:具有动态查询的游标 - 为游标字段引发错误“无效标识符”
【发布时间】:2016-02-11 21:45:46
【问题描述】:

我有一个逻辑来实现我必须使用动态 sql 的地方(列名和 where 子句是动态决定的)。所以这里我的光标(emp_ref_cursor)有一个动态 sql,并且有 3 个游标字段(emp_id,emp_name,dept)。

在WHERE 子句中使用这些游标字段,我试图在循环中执行另一个动态sql。Bt oracle 无法识别游标字段并抛出类似“ORA-00904:"EMP_REC"."EMP_ID": invalid identifier"”的错误,尽管我我能够通过DBMS_OUTPUT输出emp_rec.emp_id。

注意:请不要评论代码质量,这不是实际代码。 这只是用来描述问题。由于以下原因,我无法发布实际代码 一些合规相关的东西。

DECLARE
    emp_ref_cursor sys_refcursor; 
    v_sql varchar2(3900);

    TYPE emp_rec_type  IS RECORD (emp_id number,emp_name varchar2(100),dept_id varchar2(100)); 
    emp_rec emp_rec_type; 

    v_dept_id number:='1234';

    v_dob varchar2(100);
    v_desig varchar2(100);

    x_dynamic_col_1 varchar2(100):='dob'; --dynamic column(based on some condition)
    x_dynamic_col_2 varchar2(100):='designation'; --dynamic column(based on some condition)
    x_dynamic_col_3 varchar2(100):='emp_id'; --dynamic column(based on some condition)

BEGIN   
    v_sql:='SELECT emp_id,emp_name,dept FROM employee WHERE dept_id=' || v_dept_id;

    OPEN  emp_ref_cursor FOR  v_sql;
        LOOP
                FETCH emp_ref_cursor INTO  emp_rec;
                exit WHEN emp_ref_cursor%NOTFOUND;


                stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
                      FROM employee A
                        WHERE emp_id=emp_rec.' || x_dynamic_col_3;

                DBMS_OUTPUT.PUT_LINE(stmt); 
                --Prints the SQL query as expected

                DBMS_OUTPUT.PUT_LINE('emp_rec.emp_id:'||emp_rec.emp_id);
                --Displays the value!!!

                execute immediate stmt into v_dob, v_desig; 
                --But why is it saying emp_rec.emp_id is invalid identifier??
    END LOOP;            
END;

【问题讨论】:

    标签: oracle plsql cursor sys-refcursor ref-cursor


    【解决方案1】:

    您已将 emp_rec 定义为本地 PL/SQL 变量。没有任何 PL/SQL 数据在动态 SQL 执行的范围内。当它被执行时,就像您尝试运行该语句一样 - 正如您的 dbms_output 独立在单独的 SQL 上下文中显示的那样。如果你这样做了,很明显emp_rec 不存在于查询中。

    您需要使用绑定变量来引用它:

    WHERE emp_id=:dynamic_col_3';
    

    然后执行它:

    execute immediate stmt using emp_rec.emp_id;
    

    但您不能在using 子句中使用x_dynamic_col_3 局部变量。因为——无论如何——在这个例子中——查询也需要改变以使用不同的表列是动态记录字段改变了——这似乎不是太大的问题。但是您说where 子句也会即时更改。在这种情况下,您可以在执行之前将另一个局部变量设置为相关的x 字段。

    【讨论】:

      【解决方案2】:

      您对EXECUTE IMMEDIATE 的使用不正确。您不需要将 INTO 子句放入 SQL 查询。改用这个:

                  stmt:='SELECT ' || x_dynamic_col_1 || ',' || x_dynamic_col_2 || '
                           FROM employee A
                          WHERE emp_id=emp_rec.' || x_dynamic_col_3;
      
                  execute immediate stmt into v_dob, v_desig; 
      

      【讨论】:

      • 正确,但与 OP 遇到的错误无关?
      • 是的,我同意,但这并不是真正的工作代码(仅用于演示目的)。我的问题正是@AlexPoole 解释的。纠正它。
      猜你喜欢
      • 2021-03-13
      • 2021-01-14
      • 2014-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多