ORA-01747, ORA-06512 and other field names caused by EXECUTE IMMEDIATE USING are invalid, field names are keywords, etc.

Without further ado, let’s get straight to the questions:

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;   

When running the previous program, the problem of ORA-01747 will be prompted. By replacing the V_SQL in the above update statement with the corresponding field, it is found that the operation is successful, and it is judged that it is not the reason for the keyword contained in V_SQL. Then use the following code to output V_SQL, replace it with the corresponding: V_SQL, and find that it runs successfully.

dbms_output.put_line(V_SQL);

This indicates that the syntax of USING may be incorrect. After checking some blogs, I did not find any problems, which made me very confused. In the end, simply don’t use USING, use the | | splicing symbol to directly splice the variables into the original SQL, and the result is successful. Although the problem is solved, I don’t know why it will be solved. Variables, the other three variables are spliced, and finally TABLE_NAME, V_SQL will report an error with USING assignment. Through comparison, it is found that these two strings represent column names and table names. There is a faint flash of inspiration. In order to verify some I went to Baidu specifically for my idea: Original blog post

Sure enough, when using the execute immediate method to execute SQL statements, the table name and column name cannot be directly passed by USING, but can be executed by splicing, as follows:

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;   

Here is a bold guess: when EXECUTE IMMEDIATE executes a SQL statement, it first compiles the main SQL (that is, ignores the parameters and regards it as a placeholder), and then judges whether the SQL is compiled successfully. The parameters are replaced one by one according to the priority, and finally the execution is successful. It's just a guess, I will continue to verify it later.

おすすめ

転載: blog.csdn.net/qq_42740899/article/details/103487761