【问题标题】:Oracle Alter Table using Execute Immediate Not behaving as expectedOracle Alter Table 使用 Execute Immediate 未按预期运行
【发布时间】:2021-02-18 13:29:04
【问题描述】:

我有像下面这样的 PLSQL 块,它添加一个虚拟列,进行更新,然后删除并重命名列

BEGIN
NULL;
EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH ADD (TEMP_745634_1 VARCHAR2(4000 BYTE))';
UPDATE TESTMISMATCH SET TEMP_745634_1=TO_CHAR(A);
EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH DROP COLUMN A';
EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH RENAME COLUMN TEMP_745634_1 TO A';
End; 

第一个执行立即语句成功,但新创建列上的以下 UPDATE 语句失败并出现以下错误

ORA-06550: line 4, column 25:
PL/SQL: ORA-00904: "TEMP_745634_1": invalid identifier
ORA-06550: line 4, column 1:

但是如果我在没有 plsql 块的情况下运行相同的语句,所有语句都会成功执行,如下所示。

ALTER TABLE TESTMISMATCH ADD (TEMP_745634_1 VARCHAR2(4000 BYTE));
UPDATE TESTMISMATCH SET TEMP_745634_1=TO_CHAR(A);
ALTER TABLE TESTMISMATCH DROP COLUMN A;
ALTER TABLE TESTMISMATCH RENAME COLUMN TEMP_745634_1 TO A;

我最初的怀疑是关于第一个“立即执行”语句和更新语句之间发生的 PLSQL 上下文和 SQL 上下文切换。

【问题讨论】:

    标签: sql oracle plsql alter-table


    【解决方案1】:

    问题是 Oracle 必须先编译 PL/SQL 块才能执行它。当它试图编译该块时,它发现temp_745634_1 不是一个有效的列名并抛出错误。这发生在 Oracle 甚至可以尝试执行包括 execute immediate 在内的各个语句之前。

    如果要在创建它的同一 PL/SQL 块中引用新创建的列,则需要将编译推迟到运行时。为此,您需要使update 语句使用动态SQL。因此,如果您执行execute immediate 'update ...,PL/SQL 块将起作用。

    【讨论】:

    • 感谢您的洞察,建议更改后,plsql 块运行成功。
    【解决方案2】:

    您在第一步中所做的更改似乎要等到块结束后才能看到。

    这对你有帮助

    BEGIN
      EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH ADD (TEMP_745634_1 VARCHAR2(4000 BYTE))';  
      execute immediate 'UPDATE TESTMISMATCH SET TEMP_745634_1=TO_CHAR(''A'')';
      EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH DROP COLUMN A';
      EXECUTE IMMEDIATE 'ALTER TABLE TESTMISMATCH RENAME COLUMN TEMP_745634_1 TO A';
    End; 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-16
      • 1970-01-01
      • 2023-03-18
      • 2011-06-10
      • 2011-01-10
      • 2019-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多