Oracle - обновление соединения - таблица без сохранения ключей
Я пытаюсь реплицировать команду "update tbl1 from tbl2" от Ingres, которая не существует в Oracle.
Поэтому я использую команду "update (select tbl1 join tbl2...)". Обе таблицы имеют определенные первичные ключи, и я думал, что мое соединение однозначно идентифицирует строки, но я все еще получаю "ORA-01779: не могу изменить столбец, который сопоставляется с таблицей, не содержащей ключа".
Вот подходящие анонимизированные определения таблиц и обновление, которое я пытаюсь выполнить:
CREATE TABLE tbl1
(
ID decimal(11) NOT NULL,
A varchar2(3) NOT NULL,
B float(7),
CONSTRAINT tbl1_pk PRIMARY KEY (ID,A)
)
;
CREATE TABLE tbl2
(
ID decimal(11) NOT NULL,
A varchar2(3) NOT NULL,
B float(15),
C float(15),
D char(1) NOT NULL,
CONSTRAINT tbl2_PK PRIMARY KEY (ID,A,D)
)
;
UPDATE
(select tbl1.b, tbl2.c
from tbl1 inner join tbl2
on tbl1.id=tbl2.id
and tbl1.a=tbl2.a
and tbl1.b=tbl2.b
and tbl1.a='foo'
and tbl2.D='a')
set b=c;
Как я могу определить свой выбор таким образом, что Oracle будет удовлетворен тем, что у меня нет никаких нарушений уникальности?
Ответы
Ответ 1
Вы должны сделать это с помощью коррелированного подзапроса
UPDATE tbl1 t1
SET t1.b = (SELECT c
FROM tbl2 t2
WHERE t1.id = t2.id
AND t1.a = t2.a
AND t1.b = t2.b
AND t2.d = 'a')
WHERE t1.a = 'foo'
AND EXISTS( SELECT 1
FROM tbl2 t2
WHERE t1.id = t2.id
AND t1.a = t2.a
AND t1.b = t2.b
AND t2.d = 'a')
Проблема с UPDATE
, которую вы написали, заключается в том, что Oracle не может гарантировать, что существует ровно 1 tbl2.c
значение, соответствующее одному значению tbl1.b
. Если в tbl2
имеется несколько строк для любой конкретной строки в tbl1
, коррелированное обновление будет вызывать ошибку, указывающую, что подстрочный ряд с одной строкой возвращал несколько строк. В этом случае вам нужно добавить некоторую логику в подзапрос, чтобы указать, какую строку из tbl2
использовать в этом случае.
Ответ 2
Этот оператор терпит неудачу с ошибкой (ORA-01779 не может изменить столбец, который сопоставляется с таблицей, не содержащей ключа), поскольку он пытается изменить базовую таблицу tbl1table, а таблица tbl1 не сохраняется в виде ключа в представлении.
потому что хотя (ID, A) является ключом таблицы dept, это не ключ к соединению.
Ответ 3
Кажется, что ваш взгляд не является сохранением ключа в соответствии с (http://www.orafaq.com/tuningguide/updateable%20view.html). Действительно, вы делаете свое соединение не по первичному ключу, который, кажется, не разрешен.