Oracle Database
結合による更新
サーチ…
前書き
広範な誤解(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