最終更新日:2025年11月20日

SQL DELETE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?

記事内に商品プロモーションを含む場合があります。

DELETE文はデータ削除というシンプルな操作でありながら、JOINの扱い・返り値・行数制御・制約チェックなど、RDBMSごとにじわっとクセが出る領域。
ここでは MySQL・PostgreSQL・SQL Server を横並びにして、違いを整理していく。

基本のDELETE構文はほぼ共通

最も基本的なDELETE文はどのDBでもそのまま動く。

DELETE FROM users
WHERE id = 1;

このレベルは3製品とも大差なし。ただし、削除対象の行数制御やJOINを使うかどうかで違いが出始める。

JOIN付きDELETEの構文差

DELETEにJOINを絡めたいシーンは現場で意外と多い。ここが3製品で最も違う部分。

MySQL(DELETEに直接JOINが書ける)

DELETE u
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 1000;

PostgreSQL(USING句を使う)

DELETE FROM users u
USING orders o
WHERE u.id = o.user_id
  AND o.amount > 1000;

SQL Server(FROM句でJOIN)

DELETE u
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 1000;

ややこしいが、MySQLとSQL Serverは似た書き方で、PostgreSQLはUSINGを使う。

削除された行を返す仕組み(RETURNING / OUTPUT)

UPDATE・INSERT同様、DELETE後の値を返したいケースは実務で多い。

MySQL

8.0.16以降で限定的にDELETE ... RETURNINGが利用可能。

DELETE FROM users
WHERE id = 1
RETURNING id, name;

PostgreSQL

RETURNINGがフル対応で非常に使いやすい。

DELETE FROM users
WHERE id = 1
RETURNING id, name;

SQL Server

OUTPUT句で対応。

DELETE FROM users
OUTPUT deleted.id, deleted.name
WHERE id = 1;

削除前の値が欲しいなら、deleted.が使えるSQL Serverは特に便利。

LIMIT / TOP による行数制御

DELETEで行数を制限する場合は、DBごとに構文が大きく異なる。

MySQL(LIMITが使える)

DELETE FROM logs
ORDER BY created_at
LIMIT 100;

PostgreSQL(DELETEにLIMITは不可)

サブクエリで代替する必要がある。

DELETE FROM logs
WHERE id IN (
  SELECT id FROM logs
  ORDER BY created_at
  LIMIT 100
);

SQL Server(TOPが使える)

DELETE TOP (100) FROM logs
WHERE status = 'old';

トランザクションと制約の動作差

MySQL

PostgreSQL

SQL Server

正規表現を使ったDELETE

MySQL

DELETE FROM users
WHERE name REGEXP '^A';

PostgreSQL

DELETE FROM users
WHERE name ~ '^A';

SQL Server

正規表現が標準サポートされないため、LIKEで代替する必要がある。

削除の戻り値としての行数

3製品とも「削除された行数」はクライアントレイヤーで取得可能。
ただし、SQLそのものに標準化された方法はないため、RETURNING/OUTPUTで値を返す方法が最も確実。

まとめ

DELETE文は基本形こそ共通しているものの、次のポイントで差が大きく出る。

特にJOINと行数制御はDBごとの癖が強いため、マルチDB環境では書き換えポイントとして意識しておくと安全。

基本構文比較

項目MySQLPostgreSQLSQL Server
基本DELETE構文共通共通共通
WHERE句共通共通共通
サブクエリ共通共通共通
外部キー制約InnoDBで有効標準SQL準拠で厳格柔軟だが動作特徴あり

JOINを使ったDELETE

内容MySQLPostgreSQLSQL Server
JOINの書き方DELETE ... FROM ... JOINDELETE ... USINGDELETE ... FROM ... JOIN
JOIN例DELETE u FROM users u JOIN oDELETE FROM u USING oDELETE u FROM users u JOIN o
マルチテーブルDELETE対応非対応非対応

RETURNING / OUTPUT の対応

DB削除後の行を返す方法
MySQLDELETE ... RETURNING(8.0.16+)DELETE ... RETURNING id
PostgreSQLRETURNING全面対応DELETE ... RETURNING id
SQL ServerOUTPUTDELETE ... OUTPUT deleted.id

行数制御(LIMIT / TOP)

DB行数制御方法
MySQLLIMITDELETE ... LIMIT 100
PostgreSQL非対応(サブクエリ使用)WHERE id IN (SELECT id ... LIMIT 100)
SQL ServerTOPDELETE TOP (100) FROM ...

正規表現によるDELETE

DB正規表現サポート構文
MySQL対応REGEXP
PostgreSQL対応~
SQL Server非対応LIKEで代替

日付関連の削除条件の違い(代表例)

操作MySQLPostgreSQLSQL Server
現在日時取得NOW()NOW()GETDATE()
日付比較の例created_at < NOW()同左同左

DELETE自体に直接差はないが、条件式で関数が異なる点は注意。

特徴まとめ

特徴MySQLPostgreSQLSQL Server
JOIN付きDELETEの書きやすさ高い標準寄り(USING)高い
RETURNING(削除行返却)限定的最強OUTPUTで対応
行数制御簡単手間簡単
正規表現条件対応対応非対応
標準SQL準拠度
SQL DELETE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?の商品をアマゾンで調べる。
SQL INSERT徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQL SELECT徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQL UPDATE徹底比較:MySQL・PostgreSQL・SQL Serverでどう書く?
sect: Sqls | lastmod: 2025-11-20 | pv: 0
SQLServer nolockを使ってテーブルをロックせずにSELECTする
sect: Teches | lastmod: 2019-04-30 | pv: 10121
phpMyAdminでcount(): Parameter must be an array or an object that implements Countable
sect: Teches | lastmod: 2018-11-17 | pv: 20