コマンド道場

DELETE(行を消す)の使い方

条件に合う行が表から消える

shain実行前

shain_idname
16山本
1鈴木
2佐藤
3田中

shain実行後

shain_idname
1鈴木
2佐藤
3田中

DELETE FROM shain WHERE taishoku_on < '2025-01-01'

  • 取り消し線= この文で表から消える行です
  • 実行前 18実行後 171減ります消えた行は戻せません

18 行が 17 行になります。消えるのは条件に合う行だけで、それ以外の行はそのまま残ります。

DELETE は表から行を消します。 SELECT と違って元の表そのものが変わり、消した行は戻せません。いちばんの落とし穴は WHERE の書き忘れで、エラーも確認も無しに全行が消えます

未確認の製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database

未確認: IBM Db2

製品ごとの対応表(根拠つき)を見る

このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。

01消えるのは WHERE に合う行だけ

結論: DELETE FROM 表 WHERE 条件 で、条件に合う行だけが消えます。

SELECT は表を読むだけですが、DELETE表を書き換えます。実行した瞬間に元の行は無くなり、SELECT で探しても見つかりません。

列を指定する場所はありません。消すのは行の単位です。「ある列だけ空にしたい」なら UPDATENULL を入れます。

⚠️ 何行消えたかは実行結果として返ります。思っていた数と違ったら、その場で気づけます

1 行ずつ、何をしているか
  1. DELETE FROM shainどの表から消すか
  2. WHERE taishoku_on < '2025-01-01';★どの行を消すか(省くと全行)

2 行しかありません。短いぶん、WHERE を書き忘れても文として成立してしまいます。

2025 年より前に退職した人を消す
DELETE FROM shain
WHERE taishoku_on < '2025-01-01'
RETURNING shain_id, name, taishoku_on;
shain_idnametaishoku_on
16山本2024-03-31

1

1 行だけ消えました。同じ退職者でも高橋(2025-09-30)は条件に合わないので残っています。

02⚠️ よくある間違い:WHERE を書き忘れると全行消える

結論: WHERE の無い DELETE は、表のすべての行を消します。 警告も確認も出ません。

DELETE FROM shain;構文として正しい文です。「消す対象を指定していない」のではなく「全部が対象」という意味になります。

打つ前に必ず SELECT で数えてください。 DELETE FROM 表 WHERE 条件DELETE FROMSELECT count(*) FROM に置き換えるだけで、同じ条件に何行当たるかが分かります。

⚠️ 実行してしまってからでは、トランザクションの外なら戻せません。取り消せる操作ではないという前提で扱ってください。

消す前に、当たる行数を数える
SELECT count(*) AS kesu_kensu
FROM shain
WHERE taishoku_on < '2025-01-01';
kesu_kensu
1

1

1 行です。この数が想定と合っていることを確かめてから DELETE に書き換えます。

WHERE を書かないと全行が対象になる
DELETE FROM shain
RETURNING shain_id;
shain_id
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

18

18 行すべてが消えました。エラーにも警告にもなりません。⚠️ このページの例は 1 つずつ独立した状態で実行しているので、次の例には影響していません。

03⚠️ よくある間違い:他の表から参照されている行は消せない

結論: 外部キーで参照されている行は、そのままでは消せません。

社員表の busho_id は部署表を参照しています。社員が所属している部署を消そうとすると、参照が壊れるため拒否されます

これは表を守るための仕組みで、エラーになるほうが安全です。消したいなら、先に参照している側を消すか、参照の設定(ON DELETE)を決めておく必要があります。

⚠️ 逆に、参照されていない行は素直に消えます。社員が 1 人もいない部署は消せます。

所属者がいる部署を消そうとする
DELETE FROM busho WHERE busho_name = '開発';
ERROR: update or delete on table "busho" violates foreign key constraint "busho_parent_busho_id_fkey" on table "busho"

「violates foreign key constraint」と出ます。開発には社員がいるので、部署だけ消すと社員の所属先が行方不明になります。

誰も所属していない部署は消せる
DELETE FROM busho
WHERE busho_name = '法務'
RETURNING busho_id, busho_name;
busho_idbusho_name
6法務

1

1 行消えました。法務には社員が 1 人もいないので、参照が壊れません。

04副問い合わせで対象を決める

結論: WHERE の中で副問い合わせを使えば、別の表の条件で消す行を決められます。

「管理部署の社員を消す」は、部署名から部署番号を引いてから消します。番号を人が調べて書き写すより、そのまま問い合わせに書いたほうが安全です。

⚠️ 副問い合わせが複数行を返す可能性があるなら = ではなく IN を使ってください。= は 1 行しか受け取れず、2 行返った瞬間にエラーになります。

部署名を条件にして消す
DELETE FROM shain
WHERE busho_id IN (SELECT busho_id FROM busho
                  WHERE busho_name IN ('マーケ', '基盤'))
RETURNING shain_id, name, busho_id;
shain_idnamebusho_id
6加藤5
7吉田5
12井上7
13木村7

4

4 人消えました。マーケの 2 人と基盤の 2 人です。部署番号(7 と 5)を人が調べる必要はありません。

自分で打ってみる

このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。

押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。

解いてみる

読んだだけでは書けるようになりません。実行結果で採点します。

関連するトピック

  • INSERT行を増やすほうの操作です。
  • UPDATE行を消さずに値だけ書き換える操作です。
  • WHERE 句どの行を対象にするかの条件はこちらです。
  • IN / EXISTS副問い合わせで対象を決める書き方です。

根拠(一次情報)