MERGE с использованием переменной типа строки в PL/SQL на Oracle?

С переменной bar типа foo%ROWTYPE я могу выполнять как INSERT, так и UPDATE в PL/SQL:

INSERT INTO foo VALUES bar;
UPDATE foo SET ROW = bar WHERE id = bar.id;

Но как мне сделать MERGE? Следующий подход генерирует следующее сообщение об ошибке:

MERGE INTO foo USING bar ON foo.id = bar.id
WHEN MATCHED THEN UPDATE SET ROW = bar
WHEN NOT MATCHED THEN INSERT VALUES bar;

PL/SQL: ORA-00942: таблица или представление не существует


person Anders    schedule 16.11.2015    source источник
comment
думаю, что ответ на этот вопрос был дан на форумах оракула здесь community.oracle.com/thread/ 621511?start=0&tstart=0 посмотрите на ответ Соломона. Существует также слияние FORALL, которое может вам подойти. morganslibrary.org/reference/plsql/array_processing.html   -  person Bryan Dellinger    schedule 16.11.2015
comment
Спасибо за ваш ответ. Ответ Соломона перечисляет все поля типа строки, что лишает смысла весь смысл использования типа строки. Я не уверен, что понимаю, как здесь поможет FORALL MERGE. Однако решение от MichaelS выглядит многообещающе.   -  person Anders    schedule 17.11.2015
comment
Нет, ответ Майкла тоже не работает. Я просто получаю ORA-38104: Columns referenced in the ON Clause cannot be updated: foo.id   -  person Anders    schedule 17.11.2015
comment
Это может помочь, если вы приведете более реалистичный пример. Вы вставляете/обновляете файл foo. Но что такое бар? таблица с такой же структурой? Или просто тип строки, который вы определили ранее?   -  person Non Plus Ultra    schedule 30.11.2015
comment
@NonPlusUltra Как говорится в вопросе, bar - это переменная типа foo%ROWTYPE. foo — это таблица.   -  person Anders    schedule 02.12.2015


Ответы (1)


Ответ, который MichaelS дает в упомянутой выше ветке, должен работать нормально. Сообщение об ошибке, которое вы получаете (ORA-38104: столбцы, указанные в пункте ON, не могут быть обновлены: foo.id), предполагает, что вы пытаетесь сделать что-то похожее на следующее:

merge into foo
  using (select null from dual)
  on (foo.id = bar.id)
  when matched then update set foo.id = bar.id, foo.another_field = bar.another_field
  when not matched then insert VALUES bar;

Как указано в ошибке, столбцы, указанные в предложении «ON», не могут быть обновлены. Таким образом, следующее будет работать нормально:

merge into foo
  using (select null from dual)
  on (foo.id = bar.id)
  when matched then update set foo.another_field = bar.another_field
  when not matched then insert VALUES bar;

Если вам действительно нужно обновить foo.id, здесь есть возможное решение: Как избежать ошибки ORA-3814 при слиянии?

Изменить

Возможной альтернативой было бы сделать следующее:

update foo set row = bar where foo.id = bar.id;

if sql%rowcount = 0 then
  insert into foo values bar;
end if;

По сути, это должно приравниваться к выполнению того же действия, что и оператор слияния.

person Chrisrs2292    schedule 15.12.2015
comment
Если вам действительно не нужно использовать оператор слияния по какой-либо причине, я добавил для вас возможное альтернативное решение. Как заявил Соломон Якобсон (community.oracle.com/thread/621511?start= 0&tstart=0) вы не можете использовать тип строки в предложении when match оператора слияния - person Chrisrs2292; 16.12.2015
comment
в этом случае - вообще что быстрее вариант 1 - слить или вариант 2 - обновить и потом вставить с помощью IF - person Ashish Shetkar; 26.10.2018
comment
Лично не уверен, но, согласно ответу здесь, слияние: dba.stackexchange.com/questions/16028/ - person Chrisrs2292; 26.10.2018