Question

I am using merge command to insert a non-exist record into table. When I use simple insert command it works fine. If I use merge system always alert ORA-00904: "T"."GROUP_COMPANY_ID" invalid identifier. Once I change the ON condition to (1=1) to force be true then the merge command works fine.

What the original merge statement goes to wrong? I am very sure the table was created without double quoted name so there is not case issue here.

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';
Was it helpful?

Solution

Qualify the column names with the table aiases in the insert and update clauses

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'; 

Edit:

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

OTHER TIPS

You can't update a column that you're joining on.

Your code doesn't hurl ORA-00904, it hurls the self-explanatory 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> 

I'm running 11gR2 - perhaps the behaviour is different on an earlier release. Anyway the solution is quite simple: don't bother with the MATCHED branch:

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> 

This syntax was not valid when MERGE was introduced in 9i: we had to include both branches. But it has been supported since 10g.

If you are using 9i and so need a MATCHED branch, you must update a column which is not included in the joining clause. That would be CREATE_DATE in your example,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top