ORACLE:带有动态查询的游标 - 为游标字段抛出错误 "invalid identifier"
ORACLE: Cursor with dynamic query - throws error "invalid identifier" for cursor field
我有一个逻辑来实现我必须使用动态 sql( 列名和 where 子句是动态决定的 )。所以这里是我的光标( emp_ref_cursor
) 有一个动态的 sql,并且有 3 个游标字段 (emp_id,emp_name,dept
)。
在 WHERE
子句中使用这些游标字段 我正在尝试在 loop.Bt 内部执行另一个动态 sql oracle 无法识别游标字段并抛出类似这样的错误“ORA-00904:"EMP_REC"."EMP_ID": invalid identifier"
尽管我能够通过 DBMS_OUTPUT
输出 emp_rec.emp_id
。
NOTE: Please don't comment on the code quality this is not the actual code.
This is just used to describe the problem. I can't post the actual code due to
some compliance related stuff.
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;
您已将 emp_rec
定义为局部 PL/SQL 变量。 PL/SQL 数据的 None 在动态 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
局部变量。因为 - 无论如何在这个例子中 - 查询也需要更改为使用不同的 table 列是动态记录字段已更改 - 这似乎不是什么大问题。但是您说过 where
子句也会即时更改。在那种情况下,您可以在执行之前将另一个局部变量设置为相关的 x
字段。
您对 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;
我有一个逻辑来实现我必须使用动态 sql( 列名和 where 子句是动态决定的 )。所以这里是我的光标( emp_ref_cursor
) 有一个动态的 sql,并且有 3 个游标字段 (emp_id,emp_name,dept
)。
在 WHERE
子句中使用这些游标字段 我正在尝试在 loop.Bt 内部执行另一个动态 sql oracle 无法识别游标字段并抛出类似这样的错误“ORA-00904:"EMP_REC"."EMP_ID": invalid identifier"
尽管我能够通过 DBMS_OUTPUT
输出 emp_rec.emp_id
。
NOTE: Please don't comment on the code quality this is not the actual code. This is just used to describe the problem. I can't post the actual code due to some compliance related stuff.
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;
您已将 emp_rec
定义为局部 PL/SQL 变量。 PL/SQL 数据的 None 在动态 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
局部变量。因为 - 无论如何在这个例子中 - 查询也需要更改为使用不同的 table 列是动态记录字段已更改 - 这似乎不是什么大问题。但是您说过 where
子句也会即时更改。在那种情况下,您可以在执行之前将另一个局部变量设置为相关的 x
字段。
您对 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;