今更ながら更新可能なビューを知った

Update文って分かり難いところありません?

単純なUpdateならいいんですけどね、
Update-Selectって言われるようなサブクエリ使うようなUpdate文って
たま〜に落とし穴が在りますよね。

良くある落とし穴

先日も先輩がこれにハマってた。
【WK_986_T003】

COLUMN1(PK) COLUMN2
1 a
2 b
3 c
4 d
5 e

【WK_986_T004】

COLUMN1(PK) COLUMN2
3
5
7

こんな時表があった時、【WK_986_T003】のCOLUMN2をCOLUMN1の等しい【WK_986_T004】のCOLUMN2で上書きしたい場合。
ちょっと油断すると↓のようなSQLを書いてしまったり、しまわな。。。

update WK_986_T003 A
   set A.COLUMN2 = (select B.COLUMN2
                      from WK_986_T004 B
                     where B.COLUMN1 = A.COLUMN1)

なんとなく「where B.COLUMN1 = A.COLUMN1」のせいで"WK_986_T003"にも"WK_986_T004"にもある行だけ更新される気がするけども、
そんなことは無く結果は下記
【WK_986_T003】

COLUMN1(PK) COLUMN2
1 NULL
2 NULL
3
4 NULL
5

WK_986_T004が無い行はselectの結果が無いのでNullになってしまう。
で、COLUMN1 in (3,5)の行だけ更新する場合は↓のようにしてた。

update WK_986_T003 A
   set A.COLUMN2 = (select B.COLUMN2
                      from WK_986_T004 B
                     where B.COLUMN1 = A.COLUMN1)
where exists(
    select B.COLUMN2
      from WK_986_T004 B
     where B.COLUMN1 = A.COLUMN1)

でも、ビューアップデート?更新可能なビュー?的なしくみを使うと下記のようにも書ける。

update (
       select A.COLUMN1 as A_COLUMN1
             ,A.COLUMN2 as A_COLUMN2
             ,B.COLUMN2 as B_COLUMN2
         from WK_986_T003 A
   inner join WK_986_T004 B
           on B.COLUMN1 = A.COLUMN1
) UPD
set UPD.A_COLUMN2 = UPD.B_COLUMN2

僕的感覚では下のやり口が読みやすいし直感的かなぁと思う。

隣の席の後輩が教えてくれました。
ありがとう。