Suche…


Einführung

Im Gegensatz zu weitverbreiteten Missverständnissen (einschließlich SO) erlaubt Oracle Updates über Joins. Es gibt jedoch einige (ziemlich logische) Anforderungen. Wir veranschaulichen, was nicht funktioniert und was funktioniert anhand eines einfachen Beispiels. Eine andere Möglichkeit, dies zu erreichen, ist die MERGE-Anweisung.

Beispiele: Was funktioniert und was nicht?

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.

Stellen Sie sich vor, was passiert, wenn wir mehr als einmal den Wert 1 in der Spalte src.id , mit unterschiedlichen Werten für src.val . Offensichtlich macht das Update keinen Sinn (in JEDER Datenbank - das ist ein logisches Problem). Nun wissen wir , dass es in src.id keine Duplikate src.id , aber die Oracle-Engine weiß das nicht - also beschwert sie sich. Vielleicht glauben deshalb viele Praktizierende, dass Oracle "kein Update mit Joins hat"?

Was Oracle erwartet, ist, dass src.id eindeutig sein sollte und dass Oracle, das, dies vorher wissen würde. Einfach zu reparieren! Beachten Sie, dass dasselbe mit zusammengesetzten Schlüsseln (für mehr als eine Spalte) funktioniert, wenn der Abgleich für das Update mehr als eine Spalte verwenden muss. In der Praxis ist src.id möglicherweise PK und tgt.id kann FK sein, die auf diese PK verweist, aber dies ist für Updates mit Join nicht relevant. was relevant ist die eindeutige Einschränkung.

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

Das gleiche Ergebnis könnte mit einer MERGE-Anweisung (die einen eigenen Dokumentationsartikel verdient) erzielt werden, und ich persönlich bevorzuge MERGE in diesen Fällen, aber der Grund ist nicht, dass "Oracle keine Updates mit Verknüpfungen vornimmt". Wie dieses Beispiel zeigt, tut Oracle - Updates tun mit beitritt.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow