ORA-01779 BYPASS_UJVC
結合ビュー(Join View)に対してUPDATEを実施すると、2つの表の主キーが一致しておらず内容的にも重複がある可能性がある(対象表の同一行を複数回更新する)場合に発生する。
ORA-01779:
複数表にマップする列を変更できません。(Oracle8iの場合)
キー保存されていない表にマップする列は変更できません(Oracle9iの場合)
原因:
キー保存されていない表にマップする結合ビューの列を挿入または更新しようとしました。
処置:
基礎となる実表を直接変更してください。
結合キーが一意でない結合ビュー(Join View)に対して UPDATEを実施したい場合、Oracle8i以降の環境では BYPASS_UJVCというヒントを付けて実行するとORA-1779エラーがしない。
実際にデータ上重複することなくても、オラクルがそのように判断する事があるので、これを回避するためのもである。
ただし、BYPASS_UJVCは、11gから使用できないので注意
BYPASS_UJVC の意味は Updatable Join View Check らしい
わかりやすくいうと、1:nの関係にあるテーブルどうして、更新をかけたときに、どうなるかということである。
更新先1行 ←更新元N行 の関係が問題となる。
(更新先N行←更新元1行 は全く問題ない)
結果はどうなるのか?
実験したところ、N回更新されて、最後の行だけが有効になっているようである。
SELECT /*+ BYPASS_UJVC*/ AAA.KEY1 ,AAA.DATA1 AAA_DATA1 ,BBB.DATA1 BBB_DATA1 FROM AAA INNER JOIN BBB ON BBB.KEY1 = AAA.KEY1 ORDER BY BBB.DATA1
--Oracle11g UPDATE ( SELECT /*+ BYPASS_UJVC*/ AAA.KEY1 ,AAA.DATA1 AAA_DATA1 ,BBB.DATA1 BBB_DATA1 FROM AAA INNER JOIN BBB ON BBB.KEY1 = AAA.KEY1 ORDER BY BBB.DATA1 ) UPD SET AAA_DATA1 = AAA_DATA1 || '-' || BBB_DATA1 Error [row:13,col:2] ORA-01779: キー保存されていない表にマップする列は変更できません
MERGE文に書き換えても、1:Nの関係は変わらず、違うエラーとして発生する
--Oracle11g MERGE INTO AAA USING BBB ON (BBB.KEY1 = AAA.KEY1) WHEN MATCHED THEN UPDATE SET AAA.DATA1 = AAA.DATA1 || '-' || BBB.DATA1 Error [row:3,col:7] ORA-30926: ソース表の安定したセット行を取得できません
なので、更新元の行が1行になるように、データを加工する必要がある。
この例では、KEY1のMAX値をとるようにしてみた。
UPDATE方式だとエラーになるが、
MERRGE方式だとエラーにならない。
--Oracle11g UPDATE ( SELECT /*+ BYPASS_UJVC*/ AAA.KEY1 ,AAA.DATA1 AAA_DATA1 ,BBB.DATA1 BBB_DATA1 FROM AAA INNER JOIN ( SELECT KEY1,MAX(DATA1) DATA1 FROM BBB GROUP BY KEY1 )BBB ON BBB.KEY1 = AAA.KEY1 ORDER BY BBB.DATA1 ) UPD SET AAA_DATA1 = AAA_DATA1 || '-' || BBB_DATA1 Error [row:16,col:2] ORA-01779: キー保存されていない表にマップする列は変更できません
--Oracle11g MERGE INTO AAA USING(SELECT KEY1,MAX(DATA1) DATA1 FROM BBB GROUP BY KEY1)BBB ON (BBB.KEY1 = AAA.KEY1) WHEN MATCHED THEN UPDATE SET AAA.DATA1 = AAA.DATA1 || '-' || BBB.DATA1