サーチ…


前書き

広範な誤解(SOを含む)とは対照的に、Oracleは結合を介して更新を許可します。しかし、いくつかの(かなり論理的な)要件があります。私たちは何がうまくいかないか、そして単純な例を通して何が起こるかを説明します。同じことを達成する別の方法は、MERGEステートメントです。

例:動作するものと動作しないもの

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.

src.idの列に値1が複数回設定されていて、 src.val値が異なる場合、何が起こるかを想像してみてsrc.val 。明らかに、更新は意味をなさないでしょう(ANYデータベースで - それは論理的な問題です)。今、 私たちはには重複がないことを知ってsrc.id 、しかし、Oracleのエンジンはそれを知らない-それは文句を言っています。おそらくこれが、多くの実務家がOracleに「結合でUPDATEしていない」と考えている理由です。

オラクルが期待しているのは、 src.idは固有であるべきであり、Oracleはこれを事前に知っているということです。簡単に修正!更新の一致が複数の列を使用する必要がある場合は、複数の列にある複合キーでも同じことが働くことに注意してください。実際には、 src.idはPKであり、 tgt.idはこのPKを指し示すFKかもしれませんが、これは結合による更新には関係ありません。何関連していることはユニーク制約です。

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

MERGEステートメント(独自のドキュメンテーション記事を参照してください)でも同じ結果が得られますが、私はこれらのケースで個人的にMERGEを好むが、その理由は「Oracleは結合による更新をしない」ということではない。この例に示すように、Oracle 結合による更新を行います。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow