単一テーブル構文:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name
[WHEREwhere_condition
] [ORDER BY ...] [LIMITrow_count
]
複合テーブル構文:
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]tbl_name
[.*] [,tbl_name
[.*]] ... FROMtable_references
[WHEREwhere_condition
]
または
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROMtbl_name
[.*] [,tbl_name
[.*]] ... USINGtable_references
[WHEREwhere_condition
]
単一テーブル構文では、DELETE
ステートメントによって
tbl_name
から行が削除され、削除された行数が返されます。この数は、ROW_COUNT()
関数を呼び出すことによって取得できます
(項7.11.3. 「情報関数」 を参照)。もし
WHERE
節が与えられたら、それはどの行を削除するべきかを決定します。WHERE
節が無ければ、すべての行が削除されます。もし
ORDER BY
節が指定されると、指定された順に行が削除されます。LIMIT
節は、削除できる行数に制限を設定します。
複合テーブル条項に対しては、DELETE
はそれぞれの tbl_name
から条件を満たしている行を削除します。この場合、ORDER
BY
と LIMIT
を利用することはできません。
where_condition
は削除される各行に対して正しい結果の式です。それは
項8.2.8. 「SELECT
構文」
で述べられている通りに指定されます。
現在は、サブクエリーの中で 1 つのテーブルから削除し、同じテーブルから選択することはできません。
テーブルから行を削除するには、そのテーブルに対する
DELETE
権限が必要です。WHERE
節で指定されているカラムなどの、読み取りのみを行うカラムに対しては、SELECT
権限のみが必要です。
述べられているように、WHERE
を持たない DELETE
ステートメントはすべての行を削除します。削除された行数を知る必要がない場合、TRUNCATE
TABLE
を使用すると、この操作をより高速に実行できます。ただし、トランザクション内の場合や、テーブルにロックが設定されている場合、DELETE
は使用できますが、TRUNCATE
TABLE
は使用できません。項8.2.10. 「TRUNCATE
構文」、項8.4.5. 「LOCK TABLES
と
UNLOCK
TABLES
構文」
を参照してください。
もし AUTO_INCREMENT
カラムに対して最大値を持つ行を削除すると、その値は
MyISAM
か
InnoDB
テーブルに再度利用されることはありません。autocommit
モードで DELETE FROM
(tbl_name
WHERE
節はなし)
を使用してテーブル内のすべての行を削除する場合は、InnoDB
と MyISAM
を除くすべてのストレージエンジンに対してシーケンスが開始されます。項9.4.3. 「InnoDB
の
AUTO_INCREMENT
処理」
で紹介されているように、InnoDB
テーブルに対するこの動作にはいくつか例外があります。
MyISAM
テーブルには、複合カラムキー内の
AUTO_INCREMENT
セカンダリカラムを指定することができます。この場合、MyISAM
テーブルに対しても、シーケンスの先頭から削除された値の再利用が行われます。項1.6.9. 「AUTO_INCREMENT
の使用」
を参照してください。
DELETE
ステートメントは次の修飾子をサポートします。
もし LOW_PRIORITY
を指定すると、サーバーは別のクライアントがテーブルからの読み込みをしなくなるまで、DELETE
の実行を遅らせます。これは、テーブルレベルロックのみを使用するストレージエンジン
(MyISAM
、MEMORY
、MERGE
)
にのみ影響を与えます。
MyISAM
テーブルに対しては、もし
QUICK
キーワードを利用すると、ストレージエンジンはインデックスをマージしませんので、いくつかの削除操作のスピードが速くなります。
IGNORE
キーワードは、行削除の作業中に MySQL
がすべてのエラーを無視するように働きかけます。(解析段階で起きたエラーは通常通りの扱いになります。IGNORE
を利用したために無視されたエラーは、警告として返されます。
削除操作のスピードは 項4.2.23. 「DELETE
ステートメントの速度」
で紹介されている要因によっても影響を受ける可能性があります。
MyISAM
テーブルでは、削除された行はリンクされたリスト内で保存され、後続の
INSERT
操作は古い行の位置を再利用します。利用されていないスペースを再利用しファイルサイズを縮小するには、テーブルを確認するために
OPTIMIZE TABLE
ステートメントか
myisamchk
ユーティリティーを利用してください。OPTIMIZE
TABLE
の方が使い方は簡単ですが、myisamchk
の方が高速です。項8.5.2.5. 「OPTIMIZE TABLE
構文」、myisamchk
を参照してください。
QUICK
修飾子は、インデックスが削除操作のためにマージされるかどうかに影響を与えます。DELETE
QUICK
は、削除された行のインデックス値があとで挿入された行に似ているインデックス値と置き換えられるアプリケーションに、もっとも有効です。この場合、削除された値によって作られた穴は再利用されます。
DELETE QUICK
は、削除された値が、新しい挿入が再び行われるインデックス値の範囲にかかるアンダーフィルされたインデックスのブロックを導く場合には、有効ではありません。この場合、QUICK
の利用は、未使用のままインデックス内に残る無駄なスペースを作り出します。ここに、同じようなシナリオの例があります。
インデックスされた
AUTO_INCREMENT
カラムを含むテーブルを作成します。
テーブル内に多くの行を挿入します。各挿入は、インデックスのハイエンドに追加されるインデックス値となります。
DELETE QUICK
を利用してカラム範囲のローエンドにある行のブロックを削除します。
このシナリオの中では、削除されたインデックス値に関連するインデックスブロックはアンダーフィルされますが、QUICK
を利用することによって別のインデックスブロックとマージされることはありません。新しい行は削除された範囲内にインデックス値を持たないので、新しい挿入が行われてもそれらはアンダーフィルされたままです。その上、あとで
QUICK
なしで
DELETE
を利用しても、アンダーフィルされたブロック内またはその隣に、削除されたインデックスブロックのいくつかが偶然残っていないかぎり、それらはアンダーフィルされたままです。このような条件下で、利用されていないインデックススペースを再利用するには、OPTIMIZE
TABLE
を利用してください。
もしテーブルからたくさんの行を削除しようとしているのなら、OPTIMIZE
TABLE
が後に続く
DELETE QUICK
を利用することで処理が速くできるかもしれません。これは、たくさんのインデックスブロックのマージ操作を行うというよりは、インデックスを再構築する作業です。
MySQL
特有の、DELETE
のための LIMIT
オプションは、コントロールがクライアントに返される前に、削除されるべき最大行数をサーバーに伝えます。これは、与えられた
row_count
DELETE
ステートメントに時間がかかりすぎないことを保障します。影響される行数が
LIMIT
値よりも少なくなるまで
DELETE
ステートメントを繰り返すことができます。
DELETE
ステートメントに ORDER
BY
節が含まれている場合、行はこの節で指定された順序で削除されます。これは、主に
LIMIT
と組み合わせて使用した場合に有効です。たとえば、次のステートメントは
WHERE
節にマッチする行を見つけ、timestamp_column
を利用してそれらをソートし、そして最初の
(一番古い) 物を削除します。
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;
ORDER BY
はまた、参照整合性の違反を避けるために必要な順序で行を削除する場合にも役立つことがあります。
大きなテーブルから多数の行を削除する場合は、InnoDB
テーブルに対するロックテーブルのサイズを超える可能性があります。この問題を回避するために、または単にテーブルがロックされたままになる時間を最小限に抑えるために、DELETE
をまったく使用しない次の方法が有効な場合があります。
削除されない行を選択して、元のテーブルと同じ構造を持つ空のテーブルに格納します。
INSERT INTO t_copy SELECT * FROM t WHERE ... ;
RENAME TABLE
を使用して元のテーブルを原子的に移動したあと、コピーの名前を元の名前に変更します。
RENAME TABLE t TO t_old, t_copy TO t;
元のテーブルを削除します。
DROP TABLE t_old;
RENAME TABLE
が実行されている間、関連するテーブルにほかのセッションからはアクセスできないため、名前変更の操作は並行性の問題に制約されません。項8.1.33. 「RENAME TABLE
構文」
を参照してください。
WHERE
節内の特別な条件に依存する 1
つ、または複数のテーブルから行を削除するために、DELETE
ステートメントの中で複数のテーブルを指定することができます。しかし、複合テーブル
DELETE
の中で
ORDER BY
や
LIMIT
を利用することはできません。table_references
節は結合箇所に含まれるテーブルをリストします。その構文は
項8.2.8.1. 「JOIN
構文」 で説明されています。
最初の複合テーブル構文には、FROM
節の前にリストされた、テーブルのマッチする行だけが削除されます。2
番目の複合テーブル構文では、FROM
節 (USING
節の前)
の前にリストされた、テーブルのマッチする行だけが削除されます。その効果は、複数のテーブルから同時に行を削除でき、検索のためだけに利用される追加テーブルを持つことができるということです。
DELETE t1, t2 FROM t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;
または
DELETE FROM t1, t2 USING t1 INNER JOIN t2 INNER JOIN t3 WHERE t1.id=t2.id AND t2.id=t3.id;
これらのステートメントは、削除する行を検索するときに
3
つのテーブルすべてを利用しますが、テーブル
t1
と
t2
からのマッチする行だけを削除します。
前の例では INNER JOIN
を使用していますが、複合テーブル
DELETE
ステートメントは、SELECT
ステートメントで許可されているほかの結合型
(LEFT JOIN
など)
を使用できます。たとえば、t2
内に一致するもののない
t1
に存在する行を削除するには、LEFT
JOIN
を使用します。
DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Access
との互換性のために、この構文では、各
tbl_name
のあとに
.*
が許可されています。
外部キー制限があるテーブルに
InnoDB
テーブルを含む複合テーブル
DELETE
ステートメントを利用すると、MySQL
のオプティマイザは、それらの親子関係の順番と違う順番でテーブルを処理するかもしれません。この場合、ステートメントは失敗し、ロールバックされます。代わりに、単一テーブルから削除し、ほかのテーブルが適宜修正されるように
InnoDB
が働きかける
ON DELETE
性能に頼る必要があります。
テーブルのエイリアスを宣言する場合は、テーブルを参照するときにこのエイリアスを使用する必要があります。
DELETE t1 FROM test AS t1, test2 WHERE ...
複合テーブル
DELETE
ステートメント内のテーブルエイリアスは、table_references
部分でのみ宣言するようにしてください。ステートメント内のほかの場所では、エイリアス参照は許可されますが、エイリアス宣言は許可されません。
正しい:
DELETE a1, a2 FROM t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id; DELETE FROM a1, a2 USING t1 AS a1 INNER JOIN t2 AS a2 WHERE a1.id=a2.id;
正しくない:
DELETE t1 AS a1, t2 AS a2 FROM t1 INNER JOIN t2 WHERE a1.id=a2.id; DELETE FROM t1 AS a1, t2 AS a2 USING t1 INNER JOIN t2 WHERE a1.id=a2.id;
table_references
部分以外の場所でエイリアスを宣言すると、間違ったテーブルからの行の削除などの予期しない結果を生む、あいまいなステートメントになることがあります。これは、このようなステートメントです。
DELETE FROM t1 AS a2 USING t1 AS a1 INNER JOIN t2 AS a2;
MySQL 5.1.23
より前のバージョンでは、エイリアス宣言が
table_references
部分以外の場所でも許可されていますが、今説明した理由により避けるようにしてください。
複合テーブルの削除ではデータベースをまたがる削除がサポートされていますが、行を削除するテーブルのリストでは、明示的に指定しないかぎり、エイリアスにデフォルトデータベースが割り当てられることに注意してください。たとえば、現在のデータベースが
test
である場合、次のステートメントは、修飾されていないエイリアス
a1
に
test
のデフォルトデータベースが割り当てられているために機能しません。
DELETE a1, a2 FROM db1.t1 AS a1 INNER JOIN db2.t2 AS a2 WHERE a1.id=a2.id;
エイリアスを正しく一致させるには、エイリアスが指定されたテーブルのデータベースを使用して、エイリアスを明示的に修飾する必要があります。
DELETE db1.a1, db2.a2 FROM db1.t1 AS a1 INNER JOIN db2.t2 AS a2 WHERE a1.id=a2.id;