SQLで複数カラムを一度に更新する基本形は、UPDATEのSET句へ「列名 = 値」をカンマ区切りで並べる方法です。最も重要なのはWHERE句です。実行前に同じ条件のSELECTで対象行と件数を確認し、可能ならトランザクション内で更新結果を検証してから確定します。複数回のUPDATEへ分けるより、同じ対象行の関連カラムを1文で更新したほうが、途中状態を残しにくくなります。
複数カラム更新の基本構文
UPDATE customers
SET status = 'active',
plan_name = 'standard',
updated_at = CURRENT_TIMESTAMP
WHERE customer_id = 1205;
この例は、customer_idが1205の行について、status、plan_name、updated_atを同じ文で更新します。カンマは代入式の間に置き、最後の代入式の後には置きません。文字列はシングルクォートで囲み、列名や値の型は実際のテーブル定義に合わせます。
WHEREを省略するとテーブルの全行が対象になります。全件更新が目的でない限り、主キーや一意に絞れる条件を使い、対象件数を把握してから実行します。
目的別に書き方を選ぶ
| 更新したい内容 | 適する方法 | 確認点 |
|---|---|---|
| 対象行へ同じ値を設定 | SETへ複数代入を列挙 | WHEREの範囲 |
| 現在値から計算 | SETで式を使用 | NULLと丸め |
| 行ごとに違う値 | CASE式または更新元テーブル | 対象IDの漏れ |
| 別テーブルの値を反映 | 製品別のUPDATE結合構文 | 1行対1行になる結合 |
| 全行を更新 | WHEREなしのUPDATE | 本当に全件かを二重確認 |
同じ「複数更新」でも、複数の列を更新するのか、複数の行へ異なる値を入れるのか、複数テーブルを参照するのかで構文が変わります。最初に目的を分類すると、必要以上に複雑なSQLを避けられます。
実行前にSELECTで対象を固定する
更新文を書く前に、同じWHERE条件で対象行を表示します。更新する列だけでなく、主キーと条件判定に使う列も出すと、意図しない行を見つけやすくなります。
SELECT customer_id,
status,
plan_name,
updated_at
FROM customers
WHERE customer_id = 1205;
結果が0行なら条件が誤っている可能性があります。2行以上なら、customer_idが一意ではない、別の条件が必要、対象の理解が違う、のいずれかを確認します。件数だけでなく値も見て、更新後に何が変わるかを言葉で説明できる状態にしてからUPDATEへ進みます。
現在値から複数列を計算する
UPDATE products
SET price = price + 500,
updated_at = CURRENT_TIMESTAMP
WHERE product_id IN (101, 102);
現在値を使う式では、NULLに注意します。たとえばpriceがNULLなら、price + 500も通常はNULLです。NULLを0として扱う要件ならCOALESCE(price, 0) + 500のように明示します。ただし、NULLが「価格未設定」を表すなら0扱いは意味を変えるため、業務上の定義を確認します。
同じSET内で更新した列を次の代入式が参照する場合、評価の扱いが製品で異なることがあります。MySQLの単一テーブル更新は一般に左から右へ評価されると公式マニュアルに記載されています。製品差へ依存しないよう、各列の式を元データから明確に計算するか、先に更新値をSELECTで作って検証します。
行ごとに異なる値はCASEでまとめる
UPDATE products
SET price = CASE product_id
WHEN 101 THEN 1980
WHEN 102 THEN 2480
ELSE price
END,
updated_at = CURRENT_TIMESTAMP
WHERE product_id IN (101, 102);
この例は商品101と102へ異なる価格を設定し、更新日時は両方へ同じ値を設定します。ELSE priceは想定外の行で値を維持するための保険ですが、WHEREで対象IDを限定することの代わりにはなりません。CASEへ追加したIDとINのIDが一致しているか確認します。
対象が数十件以上になるとCASEは読みづらくなります。その場合は、更新元データをテーブルへ用意し、主キーで結合して更新する設計を検討します。ただし、SQL ServerのUPDATE ... FROM、PostgreSQLのUPDATE ... FROM、MySQLの複数テーブルUPDATE、SQLiteのUPDATE FROMは細部が同じではありません。利用中の製品の公式構文へ合わせます。
トランザクションで更新を試験する
対応するストレージと接続環境では、トランザクション内で更新し、結果を確認してからCOMMITまたはROLLBACKを選べます。次はSQL Server向けの具体例です。
BEGIN TRANSACTION;
UPDATE customers
SET status = 'active',
plan_name = 'standard',
updated_at = CURRENT_TIMESTAMP
WHERE customer_id = 1205;
SELECT customer_id,
status,
plan_name,
updated_at
FROM customers
WHERE customer_id = 1205;
ROLLBACK TRANSACTION;
最初の試験ではROLLBACK TRANSACTIONで戻し、結果が正しいことを確認します。本番実行時だけ末尾をCOMMIT TRANSACTIONにします。PostgreSQLとSQLiteではBEGIN、MySQLではSTART TRANSACTIONなど、開始構文に違いがあります。接続ツールの自動確定設定も確認し、未確認のまま共通構文だと思い込まないことが大切です。
別テーブルを使う更新は結合件数を先に確認する
別テーブルの値を反映するときは、更新文より先に同じ結合条件のSELECTを実行します。更新対象1行に対して更新元が複数行結合されると、どの値が採用されるか不明確になったり、製品ごとに異なる結果になったりします。更新対象の主キーごとに結合結果が1行であることを確認します。
PostgreSQLの公式文書も、FROMを使う場合は更新対象の各行に対して結合結果が1行以下になるようにすべきだと説明しています。重複があるなら、更新前に更新元を集約する、重複データを修正する、採用ルールを明示する、のいずれかを行います。
更新後は件数と値を検証する
- 実行前SELECTの件数と更新件数が一致するか
- 更新対象の主キーに漏れや余分がないか
- 更新した全カラムが期待値になったか
- NULL、空文字、既定値の扱いが要件どおりか
- 更新対象外のサンプル行が変わっていないか
- トランザクションを確定する前に結果を保存したか
PostgreSQLではRETURNING、SQL ServerではOUTPUTを使って更新された行を返す方法もあります。MySQLのUPDATEが返す「一致した行」と「実際に変更された行」の扱いにも注意が必要です。更新件数の意味を利用中のドライバーやツールで確認し、件数だけで成功と判断せず、更新後のSELECTで値を確認します。
失敗時の戻し方を先に用意する
確定前ならROLLBACKで戻せます。確定後に戻す必要がある場合に備え、更新前の主キーと対象列を別の安全な場所へ保存し、逆更新SQLを事前に作って検証します。全テーブルの複製が難しくても、変更対象行の旧値を保存しておけば戻せる範囲が明確になります。
逆更新も元の更新と同じく、SELECTで対象を確認し、トランザクション内で試します。誤更新後に慌てて条件の広いUPDATEを重ねると被害が広がるため、まず確定済みか未確定かを確認し、未確定ならロールバック、確定済みなら保存した旧値から復元します。
よくある質問
カラムごとにUPDATEを分けてもよいですか
必要な場合もありますが、同じ行の関連カラムを一体として変更するなら1文のほうが途中状態を残しにくくなります。トリガーや更新日時の動作、ロック時間、失敗時の扱いを確認して決めます。
WHEREなしで実行してしまったらどうしますか
トランザクションが未確定なら、追加操作をせず直ちにロールバックします。すでに確定している場合は、更新前に保存した旧値や正式なバックアップから復元します。推測で逆更新しないことが重要です。
複数DBで同じSQLを使えますか
単純な複数列SETは共通しやすい一方、UPDATE結合、結果返却、件数制限、トランザクション構文には違いがあります。対象製品の公式リファレンスを基準にします。
公式リファレンス
- Microsoft Learn:UPDATE Transact-SQL
- PostgreSQL公式文書:UPDATE
- MySQL 8.4 Reference Manual:UPDATE Statement
- SQLite公式文書:UPDATE
まとめ
複数カラムはSET 列1 = 値1, 列2 = 値2の形で一度に更新できます。実行前に同じWHEREのSELECTで対象行を確認し、トランザクション内で更新後の値を検証してから確定します。行ごとに異なる値はCASE、別テーブルからの反映は製品別の更新結合を使い、どちらも対象1行に対して更新値が1つに決まることを確認します。失敗時は未確定ならロールバック、確定後は保存した旧値から復元します。

コメント