DELETE 文でデータを削除する
WHERE を忘れた DELETE は、テーブルを空にする
SQL クエリ
DELETE FROM session_logs;1 行消すつもりで WHERE を書き忘れると、これで全行が消えます。UPDATE の書き忘れは「全行が同じ値になる」ですが、DELETE の書き忘れは「行そのものが無くなる」です。手がかりごと消えるので、気付いたときに残っているのはバックアップだけになります。
正しい形は次のとおりです。
SQL クエリ
DELETE FROM session_logs
WHERE expires_at < '2026-01-01';DELETE FROM テーブル名 に WHERE 条件 を続けます。条件に当たった行だけが消え、テーブルそのものと列の定義は残ります。「行を消す」と「表を消す」は別の命令です。
消す前に、同じ条件で件数を数える
UPDATE と同じで、先に SELECT を流します。DELETE の場合は、中身よりも件数を見るのが速いです。
SQL クエリ
-- 1. 何行消えるのかを先に数える
SELECT COUNT(*) AS target_rows
FROM session_logs
WHERE expires_at < '2026-01-01';
-- 2. 数が想定どおりなら、WHERE をそのままにして DELETE
DELETE FROM session_logs
WHERE expires_at < '2026-01-01';1,200 件のつもりが 480,000 件だった、と分かるのはこの段階です。桁が違えば、条件をどこかで書き落としています。数えるのに数秒しかかからないので、本番のデータを触るときは必ず挟んでください。
書く順番を逆にするのも効きます。先に SELECT COUNT(*) のほうを書いて条件を固め、数が合ってから頭だけを DELETE FROM に差し替える。この手順にしておけば、WHERE の無い DELETE はそもそも生まれません。
打ってから、戻せるようにしておく
もう 1 枚、安全網があります。トランザクションで囲むと、結果を見てから取り消せます。
SQL クエリ
BEGIN;
DELETE FROM session_logs WHERE expires_at < '2026-01-01';
SELECT COUNT(*) AS remaining FROM session_logs;
ROLLBACK;BEGIN から COMMIT までの間は、変更がまだ確定していません。残った件数を見て、想定どおりなら COMMIT で確定し、おかしければ ROLLBACK で無かったことにできます。
数えてから打つ、囲んでから打つ。この 2 つを組み合わせておけば、DELETE はそれほど怖い命令ではなくなります。逆に、どちらもやらずに本番へ流すのが、いちばんよくある事故の形です。
テーブル構造
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
price INT NOT NULL,
stock INT NOT NULL,
is_discontinued INT NOT NULL DEFAULT 0
);
INSERT INTO products (id, name, price, stock, is_discontinued) VALUES
(1, 'ノートPC', 100000, 10, 0),
(2, 'ワイヤレスマウス', 3000, 0, 1),
(3, '外付けSSD 1TB', 14000, 20, 0),
(4, 'ボールペン', 150, 200, 0),
(5, '古いキーボード', 2000, 0, 1);期待される出力
| id | name | price | stock |
|---|---|---|---|
| 1 | ノートPC | 100000 | 10 |
| 3 | 外付けSSD 1TB | 14000 | 20 |
| 4 | ボールペン | 150 | 200 |