Oracle MERGE повысить ошибку ORA-00904 - PullRequest
0 голосов
/ 25 ноября 2011

Я использую команду слияния для вставки несуществующей записи в таблицу. Когда я использую простую команду вставки, она работает нормально. Если я использую систему слияния, всегда предупреждаю ORA-00904: «T». «GROUP_COMPANY_ID» неверный идентификатор. Как только я изменяю условие ВКЛ на (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';

Ответы [ 3 ]

8 голосов
/ 25 ноября 2011

Вы не можете обновить столбец, к которому присоединяетесь.

1 голос
/ 25 ноября 2011

Ваш код не швыряет 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> 

Этот синтаксис был недопустим, когда MERGE был представлен в 9i: нам пришлось включить обе ветви. Но это поддерживается с 10 г.

Если вы используете 9i и вам нужна ветвь MATCHED, вы должны обновить столбец, который не включен в предложение присоединения. Это будет CREATE_DATE в вашем примере,

0 голосов
/ 25 ноября 2011

Квалифицируйте имена столбцов с именами таблиц в предложениях insert и update

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