Страницы

Поиск по вопросам

четверг, 25 октября 2018 г.

Запрос, при наличии unique constraint, выдаёт ошибку ORA-01779: нельзя изменить столбец, кот.отображает non key-preserved таблицу

В таблице user1.btable заведён unique constraint на 4 поля: c, d, e, f
Запрос
update (select a.bid a$bid, b.bid b$bid from user1.atable a join user1.btable b on a.c = b.c and a.d = b.d and a.e = b.e and b.f = 0) set a$bid = b$bid;
выдаёт ошибку
ORA-01779: нельзя изменить столбец, кот.отображает non key-preserved таблицу
Почему? Ведь обычно такая ошибка возникает по следующей причине
Ораклу надо уникально идентифицировать запись которую надо поменять. А для этого подзапрос должен использовать все столбцы в уникальном ключе. Кроме того у вас в первом случае может возникнуть проблема с тем, что для одной записи из таблицы A будет выбрано несколько строк из балицы B и тогда ораклу будет не ясно а из какой из записей B взять bid - Mike
А если в таблицу user1.atable добавить поле f, и изменить условие соединения на
on a.c = b.c and a.d = b.d and a.e = b.e and b.f = a.f
запрос ошибки не выдаёт.
Выдача SELECT * FROM V$VERSION
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production PL/SQL Release 11.2.0.1.0 - Production CORE 11.2.0.1.0 Production TNS for Linux: Version 11.2.0.1.0 - Production NLSRTL Version 11.2.0.1.0 - Production


Ответ

В описанной Вами схеме все должно работать создал подобную тестовую схему:
CREATE TABLE TEST_TABLEA( "C" VARCHAR2(10), "D" VARCHAR2(10), "E" VARCHAR2(10), "F" VARCHAR2(10), "BID" VARCHAR2(10));
CREATE TABLE TEST_TABLEB( "C" VARCHAR2(10), "D" VARCHAR2(10), "E" VARCHAR2(10), "F" VARCHAR2(10), "BID" VARCHAR2(10));
ALTER TABLE TEST_TABLEB add constraint CONSTR unique (C, D, E, F) using index;
И запрос (который Вы указывали в вопросе) на ней работает правильно, если есть constraint, но если его нет то выбрасывается исключение ORA-01779
Что бы избежать появление ошибки попробуйте следующий запрос:
update test_tablea set bid = (select b.bid from test_tableb b where test_tablea.c = b.c and test_tablea.d = b.d and test_tablea.e = b.e and b.f = 0) where exists( select b.bid from test_tableb b where test_tablea.c = b.c and test_tablea.d = b.d and test_tablea.e = b.e and b.f = 0)
или его аналог с nvl предложенный в комментариях, но тогда у Вас будет лишние update(ы).

После проверки на разных версиях БД удалось установить следующее join update НЕ заработал на Oracle версий:
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0, Oracle Database 11g Enterprise Edition Release 11.2.0.2.0.
Работает на:
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0, Oracle Database 12c Enterprise Edition Release 12.1.0.2.0, Oracle Database 12c Standard Edition Release 12.1.0.2.0.

Комментариев нет:

Отправить комментарий