【问题标题】:Oracle MERGE raise ORA-00904 errorOracle MERGE 引发 ORA-00904 错误
【发布时间】:2012-01-06 04:16:09
【问题描述】:

我正在使用合并命令将不存在的记录插入表中。当我使用简单的插入命令时,它工作正常。如果我使用合并系统总是警告 ORA-00904: "T"."GROUP_COMPANY_ID" 无效标识符。一旦我将 ON 条件更改为 (1=1) 以强制为真,那么合并命令就可以正常工作。

原来的合并语句出了什么问题?我很确定该表是在没有双引号名称的情况下创建的,因此这里没有大小写问题。

create table test
(
  create_date      DATE not null,
  group_company_id CHAR(16) not null
)

-- This is okay
INSERT INTO test (create_date, group_company_id) VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc');

-- This one will raise ORA-00904 error
MERGE INTO test T
USING (SELECT 'abc' AS group_company_id FROM DUAL) C
   ON (T.group_company_id = C.group_company_id)
-- ON (1 = 1)
WHEN NOT MATCHED THEN
     INSERT (create_date, group_company_id)
     VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc')
WHEN MATCHED THEN
     UPDATE SET group_company_id = 'abc';

【问题讨论】:

    标签: oracle merge ora-00904


    【解决方案1】:

    您无法更新您正在加入的列。

    【讨论】:

    • 其实如果表中不存在我想插入记录。所以“group_company_id”列是必须要检查的(加入条件),必须插入。
    • group_company_id = 'abc' 已经匹配到 abc 时,您不需要 WHEN MATCHED 子句来设置它。
    • 通过合并可以做到这一点,但您不能在连接中同时使用列时更新列。
    • 如果没有“WHEN MATCHED”,则语法不正确,oracle 拒绝执行它。 Oracle 警报:ORA-00905 缺少关键字
    • updateinsert 子句在 merge 命令中是可选的。 docs.oracle.com/cd/B28359_01/server.111/b28286/…
    【解决方案2】:

    您的代码不会抛出 ORA-00904,它会抛出不言自明的 ORA-38104

    SQL> MERGE INTO test T
    USING (SELECT 'abc' AS group_company_id FROM DUAL) C
       ON (T.group_company_id = C.group_company_id)
    -- ON (1 = 1)
    WHEN NOT MATCHED THEN
         INSERT (create_date, group_company_id)
         VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc')
    WHEN MATCHED THEN
         UPDATE SET group_company_id = 'abc';
      2    3    4    5    6    7    8    9     ON (T.group_company_id = C.group_company_id)
           *
    ERROR at line 3:
    ORA-38104: Columns referenced in the ON Clause cannot be updated:
    "T"."GROUP_COMPANY_ID"
    
    
    SQL> 
    

    我正在运行 11gR2 - 也许早期版本的行为有所不同。无论如何,解决方案很简单:不要打扰 MATCHED 分支:

    SQL> MERGE INTO test T
    USING (SELECT 'abc' AS group_company_id FROM DUAL) C
       ON (T.group_company_id = C.group_company_id)
    -- ON (1 = 1)
    WHEN NOT MATCHED THEN
         INSERT (create_date, group_company_id)
         VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc')
      2    3    4    5    6    7    8  /
    
    0 rows merged.
    
    SQL> 
    

    在 9i 中引入 MERGE 时,此语法无效:我们必须包含两个分支。但是从10g开始就支持了。

    如果您使用的是 9i,因此需要 MATCHED 分支,则必须更新未包含在连接子句中的列。在您的示例中,这将是 CREATE_DATE,

    【讨论】:

      【解决方案3】:

      insertupdate 子句中使用表格别名来限定列名

      WHEN NOT MATCHED THEN
        INSERT (T.create_date, T.group_company_id)
        VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc')
      WHEN MATCHED THEN
        UPDATE SET T.group_company_id = 'abc'; 
      

      编辑:

      MERGE INTO test  
      USING DUAL   
      ON (group_company_id = 'abc') 
      WHEN NOT MATCHED THEN      
            INSERT VALUES (TO_DATE('20100531', 'YYYYMMDD'), 'abc');
      

      【讨论】:

      • TC 之间消除group_company_id 的歧义
      • 谢谢,但仍然无法工作。 ORA-00904 出现在同一个地方。
      • 我用“ON (T.group_company_id = 'abc')”忽略了 C,同样的错误。我忽略了所有的别名 T 和 C,同样的错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-11
      相关资源
      最近更新 更多