web-dev-qa-db-ja.com

更新値がnullの場合、列を更新しない

次のようなクエリがあります(関数内):

UPDATE some_table SET
  column_1 = param_1,
  column_2 = param_2,
  column_3 = param_3,
  column_4 = param_4,
  column_5 = param_5
WHERE id = some_id;

ここで、param_xは関数のパラメーターです。パラメータがNULLである列を更新しない方法はありますか?たとえば、param_4param_5NULLの場合、最初の3つの列のみを更新し、column_4column_5には古い値を残します。

私が今やっている方法は:

SELECT * INTO temp_row FROM some_table WHERE id = some_id;

UPDATE some_table SET
  column_1 = COALESCE(param_1, temp_row.column_1),
  column_2 = COALESCE(param_2, temp_row.column_2),
  column_3 = COALESCE(param_3, temp_row.column_3),
  column_4 = COALESCE(param_4, temp_row.column_4),
  column_5 = COALESCE(param_5, temp_row.column_5)
WHERE id = some_id;

もっと良い方法はありますか?

42
Przemek

SELECTステートメントを削除します。必要はありません。現在の値を使用してください。

UPDATE some_table SET
  column_1 = COALESCE(param_1, column_1),
  column_2 = COALESCE(param_2, column_2),
  column_3 = COALESCE(param_3, column_3),
  column_4 = COALESCE(param_4, column_4),
  column_5 = COALESCE(param_5, column_5)
WHERE id = some_id;
69
Frank Heikens

きちんとしたトリック、Przemek、Frank&Erwinに感謝!

空の更新を避けるために、Erwinの回答を少し編集することをお勧めします。パラメータがnullの場合(つまり、「古い値を使用する」)、行の値が変更されていなくても(最初の更新後)、行は毎回更新されました。

「param_x IS NOT NULL」を追加することにより、空の更新を回避します。

UPDATE some_table SET
    column_1 = COALESCE(param_1, column_1),
    column_2 = COALESCE(param_2, column_2),
    ...
WHERE id = some_id
AND  (param_1 IS NOT NULL AND param_1 IS DISTINCT FROM column_1 OR
      param_2 IS NOT NULL AND param_2 IS DISTINCT FROM column_2 OR
     ...
 );
15
Geir Bostad

さらに、empty更新を回避するには:

UPDATE some_table SET
  column_1 = COALESCE(param_1, column_1),
  column_2 = COALESCE(param_2, column_2)
  ...
WHERE id = some_id;
AND  (param_1 IS DISTINCT FROM column_1 OR
      param_2 IS DISTINCT FROM column_2 OR
      ...
     );

これは、ターゲット列が定義されていることを前提としていますNOT NULL。それ以外の場合は、 Geirの拡張バージョン を参照してください。

14