SQLで特定のカラムを NULL に更新するには、UPDATE テーブル名 SET カラム名 = NULL を使います。
この記事では、基本構文から、NOT NULL制約でエラーになるケースの対処、CASE文での条件付きNULL更新、UPDATE JOINによる参照更新、RDBMS別(Oracle/MySQL/PostgreSQL/SQL Server)の注意点まで、実務で使えるパターンを網羅します。
この記事でわかること
・
・複数カラムを一括でNULLに更新する方法
・NOT NULL制約エラー(ORA-01407・ERROR 1048等)の原因と対処法
・CASE文で条件付きにNULLに更新する方法
・UPDATE JOINで別テーブルの条件を参照してNULLに更新する方法
・RDBMS別(Oracle・MySQL・PostgreSQL・SQL Server)の注意点
・個人情報削除・テストデータリセット等の実務パターン
・
UPDATE SET カラム = NULL の基本構文・複数カラムを一括でNULLに更新する方法
・NOT NULL制約エラー(ORA-01407・ERROR 1048等)の原因と対処法
・CASE文で条件付きにNULLに更新する方法
・UPDATE JOINで別テーブルの条件を参照してNULLに更新する方法
・RDBMS別(Oracle・MySQL・PostgreSQL・SQL Server)の注意点
・個人情報削除・テストデータリセット等の実務パターン
UPDATE文でNULLに更新する基本構文
カラムの値を NULL(値なし)にするには、SET カラム名 = NULL と記述します。
UPDATE テーブル名 SET カラム名 = NULL WHERE 条件;
実行例
-- 更新前の確認 SELECT id, name, email FROM users WHERE id = 1; -- id | name | email -- 1 | 田中 | tanaka@example.com -- NULLに更新 UPDATE users SET email = NULL WHERE id = 1; -- 更新後の確認 SELECT id, name, email FROM users WHERE id = 1; -- id | name | email -- 1 | 田中 | NULL
‘NULL’(文字列)と NULL(値なし)は全くの別物
クォーテーションで囲まないのが正しい書き方です。
SET email = NULL は「値なし」に更新します。SET email = 'NULL' は「NULLという4文字の文字列」に更新します。クォーテーションで囲まないのが正しい書き方です。
複数カラムを同時にNULLに更新する
カンマ区切りで複数のカラムをまとめて NULL にできます。1回の UPDATE 文で処理できるため、複数回に分けるよりも効率的です。
UPDATE users
SET email = NULL,
phone = NULL,
address = NULL
WHERE id = 1;
WHERE句なしのUPDATEは全行更新になるので注意
WHERE 句を省略すると、テーブル内の全行が更新されます。本番環境で誤実行すると取り返しがつきません。
-- ⚠ 全行の email が NULL になる! UPDATE users SET email = NULL;
安全な実行手順
1. まず
2.
3. トランザクション内で実行し、確認してからCOMMITする
1. まず
SELECT で対象行数を確認する2.
WHERE 句を必ず付ける3. トランザクション内で実行し、確認してからCOMMITする
-- 安全な手順(トランザクション使用) BEGIN; -- ① 対象を確認 SELECT id, email FROM users WHERE id = 1; -- ② 更新を実行 UPDATE users SET email = NULL WHERE id = 1; -- ③ 結果を確認してからコミット SELECT id, email FROM users WHERE id = 1; COMMIT; -- 問題なければ確定 -- ROLLBACK; -- 問題があれば取り消し
NULLに更新できないケース:NOT NULL制約エラー
カラムに NOT NULL 制約が設定されている場合、NULLへの更新はエラーになります。
-- NOT NULL制約があるカラムへの更新 UPDATE users SET name = NULL WHERE id = 1;
RDBMS別のエラーメッセージ
| RDBMS | エラーメッセージ | エラーコード |
|---|---|---|
| Oracle | ORA-01407: cannot update ("SCHEMA"."TABLE"."COLUMN") to NULL |
ORA-01407 |
| MySQL | ERROR 1048 (23000): Column 'column' cannot be null |
1048 |
| PostgreSQL | ERROR: null value in column "column" violates not-null constraint |
23502 |
| SQL Server | Cannot insert the value NULL into column 'column' |
515 |
NOT NULL制約を確認する方法
-- MySQL DESC テーブル名; -- Oracle SELECT column_name, nullable FROM user_tab_columns WHERE table_name = 'テーブル名'; -- PostgreSQL SELECT column_name, is_nullable FROM information_schema.columns WHERE table_name = 'テーブル名'; -- SQL Server SELECT COLUMN_NAME, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'テーブル名';
NOT NULL制約を一時的に外す(ALTER TABLE)
-- MySQL ALTER TABLE users MODIFY COLUMN email VARCHAR(255) NULL; -- PostgreSQL ALTER TABLE users ALTER COLUMN email DROP NOT NULL; -- Oracle ALTER TABLE users MODIFY (email NULL); -- SQL Server ALTER TABLE users ALTER COLUMN email VARCHAR(255) NULL;
本番DBでのALTER TABLEは慎重に
NOT NULL制約はデータ整合性を守るために存在します。外す前に「本当にNULLを許容してよいか」を設計レベルで確認してください。テスト環境で動作を確認してから本番に適用しましょう。
NOT NULL制約はデータ整合性を守るために存在します。外す前に「本当にNULLを許容してよいか」を設計レベルで確認してください。テスト環境で動作を確認してから本番に適用しましょう。
条件付きでNULLに更新する(CASE文)
特定の条件に一致する行だけ NULL にし、それ以外はそのままにしたい場合は CASE 文を使います。
-- ステータスが「退会」の場合だけ email を NULL にする
UPDATE users
SET email = CASE
WHEN status = '退会' THEN NULL
ELSE email
END;
複数カラム・複数条件での振り分け
-- 部署異動データの整理
UPDATE employees
SET department = CASE
WHEN resignation_date IS NOT NULL THEN NULL
WHEN transfer_date IS NOT NULL THEN '異動先未定'
ELSE department
END,
manager_id = CASE
WHEN resignation_date IS NOT NULL THEN NULL
ELSE manager_id
END;
CASE文を使ったUPDATEの詳細は【SQL】CASE文を使用した複数条件でのデータ更新方法を参照。
UPDATE JOINで別テーブルの条件を参照してNULLに更新する
別テーブルの情報を参照してNULLに更新するパターンです。RDBMS によって構文が異なります。
MySQL / MariaDB
-- 退会テーブルに存在するユーザーの個人情報をNULLに
UPDATE users u
JOIN withdrawals w ON u.id = w.user_id
SET u.email = NULL,
u.phone = NULL,
u.address = NULL
WHERE w.withdrawal_date IS NOT NULL;
PostgreSQL
-- PostgreSQLはFROM句を使う
UPDATE users u
SET email = NULL,
phone = NULL,
address = NULL
FROM withdrawals w
WHERE u.id = w.user_id
AND w.withdrawal_date IS NOT NULL;
Oracle / SQL Server
-- Oracle / SQL Server はサブクエリを使う
UPDATE users
SET email = NULL,
phone = NULL,
address = NULL
WHERE id IN (
SELECT user_id
FROM withdrawals
WHERE withdrawal_date IS NOT NULL
);
サブクエリを使ったUPDATEの詳細は【SQL】副問合せを使用して取得した値で更新する方法を参照。
NULLと空文字(”)の違い
NULL と空文字('')はまったく別の値です。混同するとバグの原因になります。
| NULL | 空文字(”) | |
|---|---|---|
| 意味 | 値が存在しない(未設定) | 長さ0の文字列(値はある) |
| 判定方法 | IS NULL |
= '' |
= NULL で判定 |
不可(常にFALSE) | — |
| LENGTH() | NULL | 0 |
| COALESCE(値, ‘代替’) | ‘代替’ が返る | 空文字がそのまま返る |
| Oracle の空文字 | NULLとして扱う | NULLとして格納される(Oracle特有) |
-- NULLに更新(値なし) UPDATE users SET email = NULL WHERE id = 1; -- 空文字に更新(空の文字列) UPDATE users SET email = '' WHERE id = 1; -- 確認: NULLはIS NULLで検索、空文字は = ''で検索 SELECT * FROM users WHERE email IS NULL; -- NULL行 SELECT * FROM users WHERE email = ''; -- 空文字行
Oracleのみ空文字=NULLの特例あり
Oracleでは
Oracleでは
''(空文字)を挿入・更新すると NULL として格納されます。MySQL・PostgreSQL・SQL Serverでは空文字とNULLは区別されます。Oracleから他DBへ移行する際はこの差異に注意してください。NULLに更新した値の確認方法
NULL の検索には = NULL ではなく IS NULL を使います。NULL は「不明な値」であり =(等価比較)が成立しないためです。
-- NG: = NULL では検索できない(結果は常に0件) SELECT * FROM users WHERE email = NULL; -- OK: IS NULL を使う SELECT * FROM users WHERE email IS NULL; -- NULLではないことを確認 SELECT * FROM users WHERE email IS NOT NULL;
NULLの検索・フィルタリングの詳細は【SQL】NULLの項目を検索する方法および【SQL】NULLを含むカラムでの条件分岐・フィルターの書き方を参照。
NULL伝搬:NULLを含む計算・文字列結合の注意点
カラムをNULLに更新した後、そのカラムを使った計算や文字列結合が NULL になる(NULL伝搬)ことに注意が必要です。
-- 例: price か discount がNULLだと final_price もNULLになる UPDATE orders SET final_price = price * (1 - discount) WHERE id = 1; -- price = 1000, discount = NULL の場合 -- 1000 * (1 - NULL) = NULL -- 対策: COALESCE でNULLを0に置換 UPDATE orders SET final_price = price * (1 - COALESCE(discount, 0)) WHERE id = 1;
-- 文字列結合でもNULL伝搬 -- first_name = 'John', last_name = NULL の場合 -- first_name || ' ' || last_name = NULL(NULLが伝搬) -- 対策: COALESCE で空文字に変換 SELECT COALESCE(first_name, '') || ' ' || COALESCE(last_name, '') AS full_name FROM users;
NULLの代わりにデフォルト値に戻す
NULL ではなく、カラムに設定されたデフォルト値に戻したい場合は DEFAULT キーワードを使います(全RDBMS対応)。
-- デフォルト値に戻す UPDATE users SET status = DEFAULT WHERE id = 1;
デフォルト値が設定されていないカラムに
DEFAULT を使うとエラーになるRDBMSがあります(MySQL等)。事前にテーブル定義を確認してください。RDBMS別:UPDATE SET NULL の注意点まとめ
| RDBMS | NOT NULL制約エラー | 空文字とNULL | UPDATE JOIN構文 | MERGE文対応 |
|---|---|---|---|---|
| Oracle | ORA-01407 | 同じ(空文字→NULL格納) | サブクエリ方式 | あり |
| MySQL | ERROR 1048 | 区別あり | JOIN 直接指定可 |
なし(代替あり) |
| PostgreSQL | エラーコード 23502 | 区別あり | FROM 句方式 |
あり |
| SQL Server | エラーコード 515 | 区別あり | FROM JOIN 方式 |
あり(MERGE) |
実務での活用パターン
個人情報の削除(退会処理・GDPR対応)
-- 退会ユーザーの個人情報をNULLに(論理削除の一種)
UPDATE users
SET email = NULL,
phone = NULL,
address = NULL,
birth_date = NULL
WHERE status = '退会'
AND deleted_at IS NOT NULL;
テストデータのリセット
-- テスト環境のフラグ・日付をリセット
UPDATE orders
SET shipped_date = NULL,
tracking_number = NULL,
completed_at = NULL
WHERE order_date >= '2026-01-01';
マスタ変更時の関連データクリア
-- 廃止された部署コードをNULLにする
UPDATE employees
SET department_id = NULL
WHERE department_id IN (
SELECT id FROM departments WHERE is_active = 0
);
期限切れデータのクリア
-- 有効期限が切れたトークンをNULLに
UPDATE user_sessions
SET token = NULL,
expires_at = NULL
WHERE expires_at < NOW();
大量データを分割してNULLに更新(タイムアウト対策)
-- 一度に全件更新するとロック・タイムアウトが発生する場合 -- MySQL: LIMIT で分割更新 UPDATE users SET email = NULL WHERE status = '退会' LIMIT 1000; -- → これを完了するまで繰り返す -- Oracle: ROWNUMで分割 UPDATE users SET email = NULL WHERE status = '退会' AND ROWNUM <= 1000;
よくあるトラブルと解決法
ケース1:NULLに更新したのにIS NULLで検索できない
-- 原因: OracleでVARCHAR2カラムに空文字を入れると NULLに変換される -- しかし、NULLの見え方が環境によって違う場合も -- 確認: 実際の値を確認する SELECT id, email, LENGTH(email), email IS NULL AS is_null_flag FROM users WHERE id = 1;
ケース2:UPDATEは成功したが件数が0件
-- 原因: WHERE条件に一致する行がない -- 確認: SELECT で件数を先に確認する SELECT COUNT(*) FROM users WHERE id = 999; -- 0件 → UPDATE してもROWCOUNT=0 -- MySQL: ROW_COUNT() で確認 SELECT ROW_COUNT(); -- Oracle: SQL%ROWCOUNT (PL/SQL) で確認
ケース3:ORA-01407 エラーが出る
-- ORA-01407: cannot update to NULL -- 原因: NOT NULL制約があるカラムへの更新 -- NOT NULL制約を確認 SELECT column_name, nullable, data_type FROM user_tab_columns WHERE table_name = 'USERS' AND column_name = 'NAME'; -- NULLABLE = N → NOT NULL制約あり -- 制約を外す(本当に必要な場合のみ) ALTER TABLE users MODIFY (name NULL);
ケース4:WHERE条件にNULLが含まれていて期待通りに動かない
-- NG: NULLとの比較に = を使う(常にFALSE) UPDATE users SET status = 'active' WHERE email = NULL; -- OK: IS NULL を使う UPDATE users SET status = 'active' WHERE email IS NULL;
ケース5:MySQLで strict mode のエラー
-- MySQL の sql_mode が STRICT_ALL_TABLES の場合 -- NOT NULL カラムへのNULL更新がエラーになる SHOW VARIABLES LIKE 'sql_mode'; -- 一時的に無効化(非推奨・テスト目的のみ) SET SESSION sql_mode = '';
よくある質問
UPDATE SET NULL は WHERE なしでも動きますか?
動きます。ただし WHERE を省略するとテーブルの全行が更新されます。意図せず全行をNULLにしてしまう事故が起きやすいため、必ずトランザクション内で実行し、SELECT で件数を確認してから実行しましょう。
Oracle で空文字 ” を UPDATE したら NULL になってしまった
Oracle の仕様です。Oracle ではVARCHAR2型に空文字を格納するとNULLとして扱われます。MySQL・PostgreSQL・SQL Serverでは空文字とNULLは区別されます。Oracle以外のDBへ移行する際や複数DBに接続するアプリでは注意が必要です。
NULLに更新した後に元の値に戻せますか?
COMMITする前であれば ROLLBACK で戻せます。COMMITした後は、バックアップや別テーブルへの履歴保存がない限り元の値には戻せません。重要なデータの更新はトランザクションを使い、バックアップを事前に取ることを推奨します。
NULL と 0 はどちらを使うべきですか?
意味が異なります。
NULL は「値が存在しない・未入力・不明」、0 は「値が確定していてゼロ」です。例:売上金額が0円(確定)なら0、売上がまだない・未集計なら NULL が適切です。設計段階でどちらを使うか統一しておくことが重要です。大量データをNULLに更新するとタイムアウト・ロックが発生する
一度に全件更新するとテーブルロックが長時間発生します。LIMIT(MySQL)や ROWNUM(Oracle)を使って1,000〜10,000件ずつに分割してコミットするか、メンテナンス時間帯に実行することを推奨します。
まとめ
| やりたいこと | SQL | 注意点 |
|---|---|---|
| 1カラムをNULLに | UPDATE t SET col = NULL WHERE 条件 |
WHERE必須 |
| 複数カラムを一括NULL | UPDATE t SET c1 = NULL, c2 = NULL WHERE 条件 |
1回のUPDATEで可 |
| 条件付きでNULLに | UPDATE t SET col = CASE WHEN ... THEN NULL ELSE col END |
CASE文を使う |
| 別テーブル参照でNULL | MySQL: JOIN / PG: FROM / Oracle: サブクエリ | RDBMS別に構文が違う |
| NULLになったか確認 | SELECT * FROM t WHERE col IS NULL |
= NULLは不可 |
| デフォルト値に戻す | UPDATE t SET col = DEFAULT WHERE 条件 |
DEFAULT未設定はエラー |
ポイントまとめ
・
・
・
・NULLの検索は
・NULLを含む計算・文字列結合は結果がNULLになる(NULL伝搬)に注意
・
WHERE 句を忘れると全行が更新される → 必ずトランザクション内で実行・
NOT NULL 制約があるカラムは更新できない(ALTER TABLE で解除可)・
NULL と空文字 '' は別物(Oracleは例外)・NULLの検索は
= NULL ではなく IS NULL を使う・NULLを含む計算・文字列結合は結果がNULLになる(NULL伝搬)に注意
