MW211 EXIT

devlog
MSSQL/FROM句によるUPDATE文
2015年02月03日
  まず、「UPDATE」文による更新先(出力表)と、「FROM」句による更新元(入力表)は
  以下の様に条件式で結合してあげないと、何を何で更新するのか
  訳が分からなくなり正しく動作しない。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [入力表].[列]                                                │
│    FROM [入力表]                                                           │
│    WHERE [入力表].[キー] = [出力表].[キー];                                │
└──────────────────────────────────────┘
    以下だと更新されたが意図した更新はできない。
  ┌────────────────────────────────────┐
  │UPDATE [出力表]                                                         │
  │    SET [列] = [入力表].[列]                                            │
  │    FROM [入力表]                                                       │
  └────────────────────────────────────┘
    どうも[入力表]の一件目ですべてを更新したりしているようだが(たまたまか)。
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  但し、更新先と更新元が同じ場合は、同じ表を操作することになるので結合条件不要。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [出力表].[列]                                                │
│    FROM [出力表]                                                           │
│    WHERE [出力表].[キー] = [出力表].[キー];                                │
├──────────────────────────────────────┤
│UPDATE [出力表]                                                             │
│    SET [列] = [出力表].[列]                                                │
│    FROM [出力表];                                                          │
└──────────────────────────────────────┘
  (これだと更新により値が変わらないので意味がないが、原則として覚えておく)

  なお、「FROM」句の表が一つであれば、別名をつけることもできる。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [別名].[列]                                                  │
│    FROM [出力表] AS [別名];                                                │
└──────────────────────────────────────┘
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  自己結合で「FROM」句に複数の更新先(出力表)が出現する場合は
  そのうちどれが「UPDATE」文の更新先(出力表)と一致するのか明示する必要があり
  「UPDATE」文は「AS」で別名をつけられない経緯からして
  「FROM」句側もどれか一つ別名をつけないものを用意する必要がある。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [別名].[列]                                                  │
│    FROM [出力表],                                                          │
│         [出力表] AS [別名]                                                 │
│    WHERE [別名].[キー] = [出力表].[キー];                                  │
└──────────────────────────────────────┘

  上記はOKだが、以下はお互いに譲り合ってる(別名を名乗ってる)のでNG。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [別名2].[列]                                                 │
│    FROM [出力表] AS [別名1],                                               │
│         [出力表] AS [別名2]                                                │
│    WHERE [別名2].[キー] = [別名1].[キー];                                  │
├──────────────────────────────────────┤
│UPDATE [出力表]                                                             │
│    SET [列] = [別名2].[列]                                                 │
│    FROM [出力表] AS [別名1]                                                │
│        INNER JOIN [出力表] AS [別名2]                                      │
│          ON [別名2].[キー] = [別名1].[キー];                               │
└──────────────────────────────────────┘
  「INNER JOIN」なら回避できるかと思ったが、やっぱりそれもNG。

  但し、「UPDATE」文で別名を(定義するのではなく)使用するという荒業もある。
┌──────────────────────────────────────┐
│UPDATE [別名1]                                                              │
│    SET [列] = [別名2].[列]                                                 │
│    FROM [出力表] AS [別名1],                                               │
│         [出力表] AS [別名2]                                                │
│    WHERE [別名2].[キー] = [別名1].[キー];                                  │
└──────────────────────────────────────┘
 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  従ってまとめると、一件以下の「WHERE」句が必要な気がしないでもないが
  [別名]と[出力表]は(実体として)同じ表なので、必要ないということになる。
┌──────────────────────────────────────┐
│UPDATE [出力表]                                                             │
│    SET [列] = [入力表].[列]                                                │
│    FROM [出力表] AS [別名]                                                 │
│        INNER JOIN [入力表]                                                 │
│          ON [入力表].[キー] = [別名].[キー]                                │
│    WHERE [別名].[キー] = [出力表].[キー];                                  │
├──────────────────────────────────────┤
│UPDATE [出力表]                                                             │
│    SET [列] = [入力表].[列]                                                │
│    FROM [出力表] AS [別名]                                                 │
│        INNER JOIN [入力表]                                                 │
│          ON [入力表].[キー] = [別名].[キー];                               │
└──────────────────────────────────────┘
分類:MSSQL