EXECUTE IMMEDIATE USING导致的ORA-01747,ORA-06512等字段名无效,字段名为关键字等问题

话不多说,直接上问题:

DECLARE
   V_SQL VARCHAR2(5000);
   V_UPDATE_SQL VARCHAR2(5000);
   TABLE_NAME VARCHAR2(50);
BEGIN
  FOR COL IN (SELECT COLUMN_NAME FROM USER_TAB_COLS WHERE TABLE_NAME = 'JOB_HEAD') LOOP
    V_SQL := V_SQL || COL.COLUMN_NAME || ',';
  END LOOP;
  TABLE_NAME := 'OC_JOB_SE';
  V_SQL := RTRIM(V_SQL, ',');
  V_UPDATE_SQL := 'UPDATE :TABLE_NAME SET(:V_SQL) = (SELECT :V_SQL FROM JOB_HEAD H WHERE H.JOB_ID = :A3) WHERE JOB_ID = :A4';
  EXECUTE IMMEDIATE V_UPDATE_SQL USING TABLE_NAME,V_SQL,V_SQL,201909196615219,201909196615219;
  commit;
END;   

在运行上一段程序时,会提示ORA-01747的问题,通过将上述update语句中的V_SQL进行替换为相应字段,发现运行成功,判断出并非是V_SQL中包含关键字的原因。然后通过下列代码,输出V_SQL,将其替换到相应:V_SQL上,发现成功运行。

dbms_output.put_line(V_SQL);

这表明可能USING的语法不对,通过查看一些博客,并没有发现什么问题,让我很疑惑。最后索性不用USING,用 | | 拼接符,将变量直接拼接到原SQL中去,结果运行成功,虽然解决了问题,但不知道为什么会解决让我有点不服气,随后通过,每次只用一个变量,其它三个变量用拼接的方法,最后得出TABLE_NAME,V_SQL用USING赋值会报错,通过对比发现这两个字符串代表的是列名,表名,隐隐中灵光一闪,为了验证某些想法特地去百度了一下:原博文

果然,用execute  immediate方法执行SQL语句时,关于表名,列名不能直接用USING传值,但可以用拼接的方法执行,如下:

DECLARE
   V_SQL VARCHAR2(5000);
   V_UPDATE_SQL VARCHAR2(5000);
   TABLE_NAME VARCHAR2(50);
BEGIN
  FOR COL IN (SELECT COLUMN_NAME FROM USER_TAB_COLS WHERE TABLE_NAME = 'JOB_HEAD') LOOP
    V_SQL := V_SQL || COL.COLUMN_NAME || ',';
  END LOOP;
  TABLE_NAME := 'OC_JOB_SE';
  V_SQL := RTRIM(V_SQL, ',');
  V_UPDATE_SQL := 'UPDATE '||TABLE_NAME||' SET('|| V_SQL ||') = (SELECT '|| V_SQL ||' FROM JOB_HEAD H WHERE H.JOB_ID = :A3) WHERE JOB_ID = :A4';
  EXECUTE IMMEDIATE V_UPDATE_SQL USING 201909196615219,201909196615219;
  commit;
END;   

这里有个大胆的猜想:EXECUTE IMMEDIATE执行SQL语句时,首先将主SQL编译(即无视参数,将其视为一个占位符),然后判断这条SQL是否编译通过,出错即返回,未出错就根据优先级将参数逐一替换,最后执行成功。仅仅是猜想啊,之后会继续验证。

猜你喜欢

转载自blog.csdn.net/qq_42740899/article/details/103487761