使用EXECUTE IMMEDIATE的动态SQL语法

时间:2018-04-17 15:59:55

标签: oracle dynamic-sql ora-00904 execute-immediate

动态SQL更新语句如下:

EXECUTE IMMEDIATE 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = '||i.CUSTOMER_REF_ID||' WHERE CUSTOMER_ID = '||i.CUSTOMER_ID;

l_prefix是保存表名前缀​​的参数,赋值为T_ i.CUSTOMER_REF_IDi.CUSTOMER_ID是从游标中获取的字段。

获取数据时动态语句遇到错误ORA-00904: invalid identifier

以静态方式重写时,查询工作正常:

UPDATE T_CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = i.CUSTOMER_REF_ID WHERE CUSTOMER_ID = i.CUSTOMER_ID;

我知道在动态SQL的连接中一定有问题,因为编译没问题,所以无法查明任何内容。

1 个答案:

答案 0 :(得分:2)

警告:像这样的动态SQL容易受到SQL注入攻击。尽可能重写动态SQL以使用绑定变量。

而不是像这样构建动态SQL:

L_SQL := 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = '||i.CUSTOMER_REF_ID||' WHERE CUSTOMER_ID = '||i.CUSTOMER_ID;
EXECUTE IMMEDIATE L_SQL;

使用此:

L_SQL := 'UPDATE '||l_prefix||'CRS_CUSTOMERS SET CUSTOMER_SOURCE_REF_ID = :REF_ID WHERE CUSTOMER_ID = :CUST_ID';
EXECUTE IMMEDIATE L_SQL USING i.CUSTOMER_REF_ID, i.CUSTOMER_ID;

这仍然需要在l_prefix进行SQL注入,但如果以编程方式控制该值,则可能没问题。另外,将SQL的构造和SQL的执行分为两个步骤,可以更轻松地将EXECUTE IMMEDIATE替换为DBMS_OUTPUT.PUT_LINE(SQL);,以检查查询是否存在语法错误。您还可以DBMS_OUTPUT.PUT_LINE参数i.CUSTOMER_REF_IDi.CUSTOMER_ID来检查其值。