【SQL】指定した項目を全レコード一括で更新する方法|UPDATE文・WHERE条件・CASE WHEN・サブクエリでの一括更新

SQLでテーブルの全レコードを一括で更新するには、UPDATE文を使います。WHERE句を省略すれば全行が対象になり、WHERE句を付ければ条件に合う行だけを更新できます。

この記事では、UPDATE文の基本構文から、WHERE条件付き更新複数カラムの同時更新CASE WHENでの行ごとの振り分けサブクエリ・JOINを使った高度な更新NULLの取り扱い安全に実行するためのテクニックまで、実務で必要な知識を網羅的に解説します。

この記事で学べること

  • UPDATE文の基本構文と全レコード一括更新の方法
  • WHERE句で条件を指定した部分更新
  • 複数カラムを同時に更新する書き方
  • CASE WHENで行ごとに異なる値を設定する方法
  • サブクエリを使った別テーブル参照の更新
  • UPDATE … JOIN(MySQL / 標準SQL)の使い分け
  • NULLの取り扱い(SET NULL・COALESCE)
  • 安全に実行するコツ(BEGIN/ROLLBACK・SELECT事前確認・LIMIT)
  • よくあるエラーと対処法
  • RDBMS別(MySQL / PostgreSQL / SQL Server / Oracle)の違い
スポンサーリンク

サンプルデータ

この記事では以下の employees テーブルを使って解説します。

id name department salary
1 田中太郎 営業 350000
2 鈴木花子 開発 420000
3 佐藤一郎 営業 300000
4 高橋美咲 開発 380000
5 山田健太 人事 280000
6 伊藤恵 人事 320000
7 渡辺大輔 開発 450000
8 中村由美 営業 280000
テーブル作成・データ挿入SQL(クリックで展開)
CREATE TABLE + INSERT
CREATE TABLE employees (
  id         INT PRIMARY KEY,
  name       VARCHAR(50),
  department VARCHAR(50),
  salary     INT
);

INSERT INTO employees (id, name, department, salary) VALUES
  (1, '田中太郎', '営業', 350000),
  (2, '鈴木花子', '開発', 420000),
  (3, '佐藤一郎', '営業', 300000),
  (4, '高橋美咲', '開発', 380000),
  (5, '山田健太', '人事', 280000),
  (6, '伊藤恵',   '人事', 320000),
  (7, '渡辺大輔', '開発', 450000),
  (8, '中村由美', '営業', 280000);

UPDATE文の基本構文(全レコード更新)

UPDATE文は、テーブルのデータを更新するためのSQL文です。WHERE句を省略すると、テーブル内の全レコードが更新対象になります。

基本構文
UPDATE テーブル名
SET カラム名 = 新しい値;

実行例:全社員の部署を一括変更

全レコード一括更新
-- 全社員の部署を「総務」に変更
UPDATE employees
SET department = '総務';

実行結果

Query OK, 8 rows affected (0.01 sec)
Rows matched: 8  Changed: 8  Warnings: 0

WHERE句がないため、8件すべてのレコードの department が「総務」に更新されます。

計算式を使った一括更新

SET句では計算式も使えます。全社員の給与を一律10%アップする例です。

計算式で一括更新
-- 全社員の給与を10%アップ
UPDATE employees
SET salary = salary * 1.1;

実行結果(更新後の確認)

 id | name     | department | salary
----+----------+------------+--------
  1 | 田中太郎 | 営業       | 385000
  2 | 鈴木花子 | 開発       | 462000
  3 | 佐藤一郎 | 営業       | 330000
  4 | 高橋美咲 | 開発       | 418000
  5 | 山田健太 | 人事       | 308000
  6 | 伊藤恵   | 人事       | 352000
  7 | 渡辺大輔 | 開発       | 495000
  8 | 中村由美 | 営業       | 308000

注意:WHERE句なしのUPDATEは全行に影響します。本番環境では誤って実行すると取り返しがつかないため、必ず事前にSELECTで確認してください。

WHERE句で条件を指定して更新する

WHERE句を付けると、条件に一致するレコードだけを更新できます。実務ではほとんどのUPDATEにWHERE句を付けるのが基本です。

WHERE句付きの構文
UPDATE テーブル名
SET カラム名 = 新しい値
WHERE 条件;

特定のIDを指定して更新

IDを指定して更新
-- ID=3 の佐藤一郎の給与を350000に変更
UPDATE employees
SET salary = 350000
WHERE id = 3;

複数条件での更新(AND / OR)

複数条件
-- 営業部で給与が300000未満の社員の給与を300000に引き上げ
UPDATE employees
SET salary = 300000
WHERE department = '営業'
  AND salary < 300000;

実行結果

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

→ id=8 中村由美の salary が 280000 → 300000 に更新

IN句で複数の値にマッチさせる

IN句で複数指定
-- ID が 1, 3, 8 の社員の部署を「マーケティング」に変更
UPDATE employees
SET department = 'マーケティング'
WHERE id IN (1, 3, 8);

複数カラムを同時に更新する

カンマ区切りで複数のカラムをまとめて更新できます。1回の UPDATE 文で処理するため、複数回に分けるよりも効率的です。

複数カラムを同時更新
-- ID=5 の山田健太:部署と給与を同時に変更
UPDATE employees
SET department = '開発',
    salary     = 350000
WHERE id = 5;

実行結果(更新後の確認)

 id | name     | department | salary
----+----------+------------+--------
  5 | 山田健太 | 開発       | 350000

全レコードの複数カラムを一括更新

全レコードの複数カラム更新
-- 全社員:部署を「未定」、給与を0にリセット
UPDATE employees
SET department = '未定',
    salary     = 0;

ポイント:SET句の各カラムはカンマ区切りで並べます。最後のカラムの後にはカンマを付けないでください(構文エラーになります)。

CASE WHENで行ごとに異なる値を設定する

CASE WHENを使うと、条件に応じて行ごとに異なる値を設定できます。1回のUPDATEで複雑な振り分けを実現できるため、非常に便利です。

部署ごとに異なる昇給率を適用する

CASE WHEN で条件分岐
-- 部署ごとに異なる昇給率を適用
UPDATE employees
SET salary = CASE
    WHEN department = '開発' THEN salary * 1.15  -- 開発: 15%アップ
    WHEN department = '営業' THEN salary * 1.10  -- 営業: 10%アップ
    WHEN department = '人事' THEN salary * 1.05  -- 人事: 5%アップ
    ELSE salary                    -- その他: 変更なし
END;

実行結果(更新後の確認)

 id | name     | department | salary
----+----------+------------+--------
  1 | 田中太郎 | 営業       | 385000   (350000 × 1.10)
  2 | 鈴木花子 | 開発       | 483000   (420000 × 1.15)
  3 | 佐藤一郎 | 営業       | 330000   (300000 × 1.10)
  4 | 高橋美咲 | 開発       | 437000   (380000 × 1.15)
  5 | 山田健太 | 人事       | 294000   (280000 × 1.05)
  6 | 伊藤恵   | 人事       | 336000   (320000 × 1.05)
  7 | 渡辺大輔 | 開発       | 517500   (450000 × 1.15)
  8 | 中村由美 | 営業       | 308000   (280000 × 1.10)

IDを指定して個別に値を設定する

IDごとに個別の値を設定
-- 特定の社員だけ部署を変更
UPDATE employees
SET department = CASE id
    WHEN 1 THEN 'マーケティング'
    WHEN 5 THEN '経理'
    WHEN 8 THEN '開発'
    ELSE department
END
WHERE id IN (1, 5, 8);

ポイント:CASE WHEN で全行を対象にする場合、ELSE句で現在の値を返すことで、条件に当てはまらない行を変更しないようにできます。WHERE句でさらに対象を絞れば無駄な更新を減らせます。

サブクエリを使った更新(UPDATE … SET col = (SELECT …))

サブクエリを使うと、別のテーブルの値を参照して更新できます。集計値やマスタデータを反映する場合に便利です。

部署ごとの平均給与で全社員を更新する

サブクエリで平均給与に更新
-- 各社員の給与を、所属部署の平均給与に更新
UPDATE employees e1
SET salary = (
    SELECT AVG(e2.salary)
    FROM employees e2
    WHERE e2.department = e1.department
);

実行結果(更新後の確認)

 id | name     | department | salary
----+----------+------------+--------
  1 | 田中太郎 | 営業       | 310000   (営業の平均)
  2 | 鈴木花子 | 開発       | 416667   (開発の平均)
  3 | 佐藤一郎 | 営業       | 310000
  4 | 高橋美咲 | 開発       | 416667
  5 | 山田健太 | 人事       | 300000   (人事の平均)
  6 | 伊藤恵   | 人事       | 300000
  7 | 渡辺大輔 | 開発       | 416667
  8 | 中村由美 | 営業       | 310000

別テーブルの値を参照して更新する

マスタテーブルの値を元に更新するパターンです。

別テーブル参照の更新
-- departments マスタの基本給を employees に反映
UPDATE employees
SET salary = (
    SELECT d.base_salary
    FROM departments d
    WHERE d.dept_name = employees.department
);

注意:サブクエリが複数行を返すとエラーになります。必ずサブクエリの結果が1行以下になるようにしてください。一致するデータがない場合はNULLが設定されるため、COALESCEでデフォルト値を指定するとより安全です。

UPDATE … JOIN(MySQL vs 標準SQL)

複数テーブルを結合して更新する場合、MySQLと標準SQL(PostgreSQL・SQL Server等)で構文が異なります

MySQL:UPDATE … JOIN構文

MySQL – UPDATE … JOIN
-- MySQL: departments テーブルの基本給を反映
UPDATE employees e
INNER JOIN departments d
  ON e.department = d.dept_name
SET e.salary = d.base_salary;

標準SQL(PostgreSQL):UPDATE … FROM構文

PostgreSQL – UPDATE … FROM
-- PostgreSQL: departments テーブルの基本給を反映
UPDATE employees e
SET salary = d.base_salary
FROM departments d
WHERE e.department = d.dept_name;

SQL Server:UPDATE … FROM構文

SQL Server – UPDATE … FROM … JOIN
-- SQL Server: departments テーブルの基本給を反映
UPDATE e
SET e.salary = d.base_salary
FROM employees e
INNER JOIN departments d
  ON e.department = d.dept_name;

Oracle:MERGEを使う方法

Oracle – MERGE
-- Oracle: MERGE で結合更新
MERGE INTO employees e
USING departments d
  ON (e.department = d.dept_name)
WHEN MATCHED THEN
  UPDATE SET e.salary = d.base_salary;

ポイント:JOIN を使った UPDATE は、サブクエリよりも読みやすく高速な場合が多いです。ただし構文がRDBMSごとに異なるため、使用するDBに合った書き方を選びましょう。

UPDATEでのNULLの取り扱い

UPDATEでカラムを NULL にしたり、NULL値を別の値に置き換えたりする方法を解説します。

カラムをNULLに更新する

NULLに更新
-- ID=3 の部署をNULLに設定
UPDATE employees
SET department = NULL
WHERE id = 3;

NULL はクォーテーションで囲みません。'NULL'(文字列)と NULL(値なし)はまったく別物です。

COALESCEでNULLをデフォルト値に置き換える

COALESCEでNULL回避
-- department が NULL の社員を「未配属」に更新
UPDATE employees
SET department = '未配属'
WHERE department IS NULL;

-- サブクエリの結果がNULLの場合にデフォルト値を使う
UPDATE employees
SET salary = COALESCE(
    (SELECT d.base_salary
     FROM departments d
     WHERE d.dept_name = employees.department),
    300000  -- マッチしなければ300000を設定
);

ポイント:COALESCE(値1, 値2)は、値1がNULLなら値2を返す関数です。サブクエリの結果がNULLになりうる場合に安全策として使えます。

UPDATEを安全に実行するためのコツ

UPDATE文は一度実行すると元に戻せません(COMMIT後)。本番環境で事故を防ぐために、以下のテクニックを身につけましょう。

1. トランザクションで囲む(BEGIN / ROLLBACK)

トランザクションで安全に実行
BEGIN;  -- トランザクション開始

-- 更新を実行
UPDATE employees
SET salary = salary * 1.1
WHERE department = '開発';

-- 結果を確認
SELECT * FROM employees WHERE department = '開発';

-- 問題なければ確定、問題あれば取消
COMMIT;    -- 確定する場合
-- ROLLBACK;  -- 取り消す場合

2. 事前にSELECTで対象行を確認する

事前確認のパターン
-- Step 1: まずSELECTで対象を確認
SELECT id, name, department, salary
FROM employees
WHERE department = '営業' AND salary < 300000;

-- Step 2: 問題なければUPDATEを実行(WHEREは同じ条件)
UPDATE employees
SET salary = 300000
WHERE department = '営業' AND salary < 300000;

3. LIMITでテスト実行する(MySQL限定)

LIMITでテスト(MySQL)
-- まず1件だけ更新して結果を確認
UPDATE employees
SET salary = salary * 1.1
WHERE department = '開発'
LIMIT 1;

-- 結果を確認して問題なければ全件実行
SELECT * FROM employees WHERE department = '開発';

注意:LIMITはMySQL固有の機能です。PostgreSQL・SQL Server・Oracleでは使用できません。

安全なUPDATE実行チェックリスト

チェック項目 内容
WHERE句の確認 WHERE句が正しいか、漏れがないか確認する
SELECTで事前確認 同じWHERE条件でSELECTし、対象行を確認する
トランザクション BEGIN〜COMMIT/ROLLBACKで囲んで実行する
バックアップ 大量更新前にテーブルのバックアップを取得する
影響行数の確認 更新後の Rows affected が想定通りか確認する

よくあるエラーと対処法

エラー内容 原因 対処法
WHERE句の付け忘れ 全レコードが意図せず更新される 実行前に必ずSELECTで確認。BEGINで囲む
型の不一致 数値カラムに文字列を設定 カラムの型を確認し、適切な値を指定
NOT NULL制約違反 NOT NULLカラムにNULLを設定 制約を確認し、NULLではなくデフォルト値を使用
外部キー制約違反 参照先に存在しない値を設定 参照先テーブルにデータが存在するか確認
サブクエリが複数行を返す SET col = (SELECT …) で2行以上返る WHERE条件を追加するか、集計関数(MAX, MIN等)を使用
UNIQUE制約違反 一意制約のあるカラムに重複値を設定 更新後に重複が発生しないか事前にSELECTで確認
デッドロック 複数トランザクションが互いにロック待ち 更新順序を統一し、トランザクションを短くする

RDBMS別のUPDATE構文の違い

基本的なUPDATE文の構文はどのRDBMSでも同じですが、JOINを使った更新一部の機能に違いがあります。

機能 MySQL PostgreSQL SQL Server Oracle
基本構文 UPDATE SET WHERE UPDATE SET WHERE UPDATE SET WHERE UPDATE SET WHERE
JOIN更新 UPDATE … JOIN … SET UPDATE … SET … FROM UPDATE … SET … FROM … JOIN MERGE INTO … USING
LIMIT LIMIT n 非対応(CTEで代替) TOP n ROWNUM
RETURNING句 非対応 RETURNING * OUTPUT句 RETURNING INTO
CASE WHEN 対応 対応 対応 対応
トランザクション BEGIN / COMMIT BEGIN / COMMIT BEGIN TRAN / COMMIT 自動(COMMIT必須)

まとめ

更新パターン SQL 用途
全レコード更新 UPDATE t SET col = val 一括リセット・一律変更
条件付き更新 UPDATE t SET col = val WHERE ... 特定行だけを変更
複数カラム更新 SET col1 = val1, col2 = val2 一度に複数項目を変更
CASE WHEN SET col = CASE WHEN ... END 行ごとに異なる値を設定
サブクエリ SET col = (SELECT ...) 別テーブルの値を参照して更新
JOIN更新 UPDATE ... JOIN ... SET 結合した結果で更新(MySQL)
NULL設定 SET col = NULL 値をNULLにクリア
NULL回避 COALESCE(val, default) NULLの場合にデフォルト値を使用

UPDATE文はSQLの中でも影響範囲が大きい操作です。WHERE句の指定漏れで全行を意図せず更新してしまう事故は、現場でもよく発生します。必ずSELECTで事前確認し、トランザクション内で実行することを習慣にしましょう。

関連記事