11gR2 MERGE + CHECK CONSTRAINT = Bug

suPPLer
Дата: 01.12.2009 17:22:24
Всем привет!

Поиском не нашёл, потому создаю тему. В Oracle DB 11gR2 наткнулся на, кмк, баг. Данные:
create table test_merge as select 1 m, 2 n from dual;

alter table test_merge add constraint test_merge_chk check (m <= n);

update test_merge set n = m - 1;

rollback;

select * from test_merge;

merge into test_merge tgt 
using (select m, m-1 n from test_merge) src
   on (tgt.m = src.m)
 when matched then update set tgt.n = src.n;
 
commit;

select * from test_merge;

В 11gR2:

SQL> @test.sql

Таблица создана.


Таблица изменена.

update test_merge set n = m - 1
*
ошибка в строке 1:
ORA-02290: нарушено ограничение целостности CHECK(XXX.TEST_MERGE_CHK)



Откат завершен.


         M          N
---------- ----------
         1          2


1 строка объединена.


Фиксация обновлений завершена.


         M          N
---------- ----------
         1          0

Это же в 11.1.0.7 и в 9.2.0.6 (с добавленной инструкцией WHEN NOT MATCHED, без которой MERGE в девятке не заработает) честно даёт ошибку:
SQL> @test.sql

Таблица создана.


Таблица изменена.

update test_merge set n = m - 1
*
ошибка в строке 1:
ORA-02290: нарушено ограничение целостности CHECK(XXX.TEST_MERGE_CHK)



Откат завершен.


         M          N
---------- ----------
         1          2

merge into test_merge tgt
*
ошибка в строке 1:
ORA-02290: нарушено ограничение целостности CHECK(XXX.TEST_MERGE_CHK)



Фиксация обновлений завершена.


         M          N
---------- ----------
         1          2

Если кто-то уже встречался - дайте, пожалуйста, номер бага на металинке, чтобы я сэкономил время нашим АБД. И если кто способ обойти скажет, то буду очень благодарен. Кроме как отказаться от MERGE вообще для подобной ситуации, ничего в голову не приходит. :(
-------------------------------------------------------
When I say "RTFM" or "STFF" or "STFW",
the third letter means "Following" or "Fine"...
andrey_anonymous
Дата: 01.12.2009 17:35:29
suPPLer
И если кто способ обойти скажет

merge into test_merge tgt 
using (select m, m-1 n from test_merge WHERE M < (M-1)) src
   on (tgt.m = src.m)
 when matched then update set tgt.n = src.n;
suPPLer
Дата: 01.12.2009 17:45:36
andrey_anonymous,

это, конечно, способ - дублировать логику ограничения в запросе, хоть и не без недостатков. Спасибо за пример, я подумаю. :)
suPPLer
Дата: 03.12.2009 13:39:55
Как оказалось, всё намного веселей. Если указать ветку WHEN NOT MATCHED, проверки начинают срабатывать. Так что обход бага прост: если ветки WHEN NOT MATCHED нет, и вставлять ничего не нужно, то
merge into test_merge tgt 
using (select m, m-1 n from test_merge) src
   on (tgt.m = src.m)
 when matched then update set tgt.n = src.n
 when not matched then insert (m, n) values(src.m, src.n) where 1 = 0;
PS: Осталось только каждый такой MERGE в коде окружать комментариями для будущих коллег-оптимизаторов...
-------------------------------------------------------
When I say "RTFM" or "STFF" or "STFW",
the third letter means "Following" or "Fine"...
orawish
Дата: 03.12.2009 14:18:37
suPPLer
Как оказалось, всё намного веселей. Если указать ветку WHEN NOT MATCHED, проверки начинают срабатывать. Так что обход бага прост: если ветки WHEN NOT MATCHED нет, и вставлять ничего не нужно, то
..

~
when not matched then insert (m) values(null) where 1 = 0
не в том даже дело, что меньше буквов, а дуало-дуризм виднее :)
suPPLer
Дата: 03.12.2009 14:28:07
orawish,

да, недоредактировал готовый вариант, спасибо.