Oracle Database
Aktualizuj za pomocą połączeń
Szukaj…
Wprowadzenie
Przykłady: co działa, a co nie
create table tgt ( id, val ) as
select 1, 'a' from dual union all
select 2, 'b' from dual
;
Table TGT created.
create table src ( id, val ) as
select 1, 'x' from dual union all
select 2, 'y' from dual
;
Table SRC created.
update
( select t.val as t_val, s.val as s_val
from tgt t inner join src s on t.id = s.id
)
set t_val = s_val
;
SQL Error: ORA-01779: cannot modify a column which maps to a non key-preserved table
01779. 00000 - "cannot modify a column which maps to a non key-preserved table"
*Cause: An attempt was made to insert or update columns of a join view which
map to a non-key-preserved table.
*Action: Modify the underlying base tables directly.
Wyobraź sobie, co by się stało, gdybyśmy mieli wartość 1
w kolumnie src.id
więcej niż raz, z różnymi wartościami dla src.val
. Oczywiście aktualizacja nie miałaby sensu (w DOWOLNEJ bazie danych - to logiczny problem). Teraz wiemy, że nie ma duplikatów w src.id
, ale silnik Oracle nie wie, że - tak to jest sędzią. Być może dlatego tak wielu praktyków uważa, że Oracle „nie ma aktualizacji z połączeniami”?
Oracle oczekuje, że src.id
powinien być unikalny, i że on, Oracle, będzie o tym wiedział wcześniej. Łatwo naprawione! Pamiętaj, że to samo działa z kluczami złożonymi (w więcej niż jednej kolumnie), jeśli dopasowanie dla aktualizacji wymaga użycia więcej niż jednej kolumny. W praktyce src.id
może być PK, a tgt.id
może oznaczać FK wskazujący na ten PK, ale nie dotyczy to aktualizacji z łączeniem; co jest istotne jest ograniczenie przez unikalność.
alter table src add constraint src_uc unique (id);
Table SRC altered.
update
( select t.val as t_val, s.val as s_val
from tgt t inner join src s on t.id = s.id
)
set t_val = s_val
;
2 rows updated.
select * from tgt;
ID VAL
-- ---
1 x
2 y
Ten sam wynik można osiągnąć za pomocą instrukcji MERGE (która zasługuje na własny artykuł z dokumentacji), a ja osobiście wolę MERGE w tych przypadkach, ale powodem nie jest to, że „Oracle nie dokonuje aktualizacji z łączeniami”. Jak pokazuje ten przykład, Oracle dokonuje aktualizacji z łączeniami.