DELETE(行を消す)の使い方
shain実行前
| shain_id | name |
|---|---|
| 16 | 山本✕ |
| 1 | 鈴木 |
| 2 | 佐藤 |
| 3 | 田中 |
| … | |
shain実行後
| shain_id | name |
|---|---|
| 1 | 鈴木 |
| 2 | 佐藤 |
| 3 | 田中 |
| … | |
DELETE FROM shain WHERE taishoku_on < '2025-01-01'
- 取り消し線= この文で表から消える行です
- 実行前 18 行 → 実行後 17 行(1 行減ります。消えた行は戻せません)
18 行が 17 行になります。消えるのは条件に合う行だけで、それ以外の行はそのまま残ります。
DELETE は表から行を消します。 SELECT と違って元の表そのものが変わり、消した行は戻せません。いちばんの落とし穴は WHERE の書き忘れで、エラーも確認も無しに全行が消えます。
未確認の製品があります そのまま使える: PostgreSQL / MySQL / MariaDB / SQLite / SQL Server / Oracle Database
未確認: IBM Db2
このページの実行結果と図は、すべて本物のデータベースに同じ SQL を流して得たものです。手で書いた「たぶんこうなる」ではありません。
01消えるのは WHERE に合う行だけ
結論: DELETE FROM 表 WHERE 条件 で、条件に合う行だけが消えます。
SELECT は表を読むだけですが、DELETE は表を書き換えます。実行した瞬間に元の行は無くなり、SELECT で探しても見つかりません。
列を指定する場所はありません。消すのは行の単位です。「ある列だけ空にしたい」なら UPDATE で NULL を入れます。
⚠️ 何行消えたかは実行結果として返ります。思っていた数と違ったら、その場で気づけます。
DELETE FROM shainどの表から消すかWHERE taishoku_on < '2025-01-01';★どの行を消すか(省くと全行)
2 行しかありません。短いぶん、WHERE を書き忘れても文として成立してしまいます。
DELETE FROM shain
WHERE taishoku_on < '2025-01-01'
RETURNING shain_id, name, taishoku_on;| shain_id | name | taishoku_on |
|---|---|---|
| 16 | 山本 | 2024-03-31 |
(1 行)
1 行だけ消えました。同じ退職者でも高橋(2025-09-30)は条件に合わないので残っています。
02⚠️ よくある間違い:WHERE を書き忘れると全行消える
結論: WHERE の無い DELETE は、表のすべての行を消します。 警告も確認も出ません。
DELETE FROM shain; は構文として正しい文です。「消す対象を指定していない」のではなく「全部が対象」という意味になります。
打つ前に必ず SELECT で数えてください。 DELETE FROM 表 WHERE 条件 の DELETE FROM を SELECT count(*) FROM に置き換えるだけで、同じ条件に何行当たるかが分かります。
⚠️ 実行してしまってからでは、トランザクションの外なら戻せません。取り消せる操作ではないという前提で扱ってください。
SELECT count(*) AS kesu_kensu
FROM shain
WHERE taishoku_on < '2025-01-01';| kesu_kensu |
|---|
| 1 |
(1 行)
1 行です。この数が想定と合っていることを確かめてから DELETE に書き換えます。
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 = '開発';「violates foreign key constraint」と出ます。開発には社員がいるので、部署だけ消すと社員の所属先が行方不明になります。
DELETE FROM busho
WHERE busho_name = '法務'
RETURNING busho_id, busho_name;| busho_id | busho_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_id | name | busho_id |
|---|---|---|
| 6 | 加藤 | 5 |
| 7 | 吉田 | 5 |
| 12 | 井上 | 7 |
| 13 | 木村 | 7 |
(4 行)
4 人消えました。マーケの 2 人と基盤の 2 人です。部署番号(7 と 5)を人が調べる必要はありません。
自分で打ってみる
このページの例と同じデータが入った本物のデータベースを、この場(あなたのブラウザの中)で起動できます。打った SQL がサーバーへ送られることはありません。
押すと初回だけ約 9MB を読み込みます(2 回目以降はキャッシュされます)。
解いてみる
読んだだけでは書けるようになりません。実行結果で採点します。
関連するトピック
- INSERT行を増やすほうの操作です。
- UPDATE行を消さずに値だけ書き換える操作です。
- WHERE 句どの行を対象にするかの条件はこちらです。
- IN / EXISTS副問い合わせで対象を決める書き方です。
根拠(一次情報)
- PostgreSQL 18 マニュアル: DELETE一次情報・確認 2026-08-13
- PostgreSQL 18 マニュアル: 外部キー制約一次情報・確認 2026-08-13