ORACLE:带有动态查询的游标 - 抛出错误"无效的标识符"对于光标字段

时间:2016-02-11 21:45:46

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

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

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

  

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

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;

2 个答案:

答案 0 :(得分:2)

您将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;

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

答案 1 :(得分:1)

您使用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;