DELETE 構文

単一テーブル構文:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

複合テーブル構文:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    tbl_name[.*] [, tbl_name[.*]] ...
    FROM table_references
    [WHERE where_condition]

または:

DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
    FROM tbl_name[.*] [, tbl_name[.*]] ...
    USING table_references
    [WHERE where_condition]

単一テーブル構文に対しては、DELETE ステートメントが tbl_name から行を削除し、削除された行数を返します。もし WHERE 条項が与えられたら、それはどの行を削除するべきかを決定します。WHERE 条項が無ければ、全ての行が削除されます。もし ORDER BY 条項が指定されると、指定された順に行が削除されます。LIMIT 条項は、削除できる行数に制限を設定します。

複合テーブル条項に対しては、DELETE はそれぞれの tbl_name から条件を満たしている行を削除します。この場合、ORDER BYLIMIT を利用する事はできません。

where_condition は削除される各行に対して正しい結果の式です。それは 項 「SELECT 構文」 で述べられている通りに指定されます。

述べられているように、WHERE を持たない DELETE ステートメントは全ての行を削除します。削除された行数を知る必要がない場合にこの作業を速く行うには、TRUNCATE TABLE を利用してください。詳しくは 項 「TRUNCATE 構文」 を参照してください。

もし AUTO_INCREMENT カラムに対して最大値を持つ行を削除すると、その値は MyISAMInnoDB テーブルに再度利用される事はありません。AUTOCOMMIT モードで DELETE FROM tbl_name を利用してテーブルの中の全ての行を削除すると(WHERE 条項なしで)、InnoDBMyISAM 以外は全てのストレージ エンジンに対してシーケンスが始まります。項3. 「AUTO_INCREMENT カラムが InnoDB 内でどのように機能するか」 で紹介されているように、InnoDB テーブルに対するこの動作にはいくつか例外があります。

MyISAM テーブルには、複合カラム キー内の AUTO_INCREMENT セカンダリ カラムを指定する事ができます。この場合、MyISAM テーブルに対しても、シーケンスの先頭から削除された値の再利用が行われます。詳しくは Using AUTO_INCREMENT を参照してください。

DELETE ステートメントは次の修飾因子をサポートします。

削除操作のスピードは 項 「DELETEステートメントの速度」 で紹介されている要因によっても影響を受ける可能性があります。

MyISAM テーブルでは、削除された行はリンクされたリスト内で保存され、後続の INSERT 操作は古い行の位置を再利用します。利用されていないスペースを再利用しファイル サイズを縮小するには、テーブルを確認する為に OPTIMIZE TABLE ステートメントか myisamchk ユーティリティを利用してください。OPTIMIZE TABLE の方が簡単ですが、myisamchk の方が速いです。項5. 「OPTIMIZE TABLE 構文」、項7.4. 「myisamchk — MyISAM テーブル メンテナンス ユーティリティ」 を参照して下さい。

QUICK 修飾因子は、インデックスが削除操作の為にマージされるかどうかに影響を与えます。DELETE QUICK は、削除された行のインデックス値が後で挿入された行に似ているインデックス値と置き換えられるアプリケーションに、最も有効です。この場合、削除された値によって作られた穴は再利用されます。

DELETE QUICK は、削除された値が、新しい挿入が再び行われるインデックス値の範囲にかかるアンダーフィルされたインデックスのブロックを導く場合には、有効ではありません。この場合、QUICK の利用は、未使用のままインデックス内に残る無駄なスペースを作り出します。ここに、同じようなシナリオの例があります。

  1. インデックスされた AUTO_INCREMENT カラムを含むテーブルを作成します。

  2. テーブル内に多くの行を挿入します。各挿入は、インデックスのハイ エンドに追加されるインデックス値となります。

  3. 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;

WHERE 条項内の特別な条件に依存する1つ、または複数のテーブルから行を削除する為に、DELETEステートメントの中で複数のテーブルを指定する事ができます。しかし、複合テーブル DELETE の中で ORDER BYLIMIT を利用する事はできません。table_references 条項は接合箇所に含まれるテーブルをリストします。その構文は 項1. 「JOIN 構文」 で説明されています。

最初の複合テーブル構文には、FROM 条項の前にリストされた、テーブルのマッチする行だけが削除されます。2番目の複合テーブル構文では、FROM 条項(USING 条項の前) の前にリストされた、テーブルのマッチする行だけが削除されます。その効果は、複数のテーブルから同時に行を削除でき、検索の為だけに利用される追加テーブルを持つ事ができるという事です。

DELETE t1, t2 FROM t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

または:

DELETE FROM t1, t2 USING t1, t2, t3 WHERE t1.id=t2.id AND t2.id=t3.id;

これらのステートメントは、削除する行を検索する時に3つのテーブル全てを利用しますが、テーブル t1t2 からのマッチする行だけを削除します。

前出の例はカンマ演算子を利用する内部接合を表しますが、複合テーブルの DELETE ステートメントは、LEFT JOIN のような、SELECT ステートメント内で許容される接合タイプを利用する事ができます。

構文は Access を持つ互換性のテーブル名の後に .* を許容します。

外部キー制限があるテーブルに InnoDB テーブルを含む複合テーブル DELETE ステートメントを利用すると、MySQL のオプチマイザは、それらの親子関係の順番と違う順番でテーブルを処理するかもしれません。この場合、ステートメントは失敗し、ロールバックされます。代わりに、単一テーブルから削除し、他のテーブルが適宜修正されるように InnoDB が働きかける ON DELETE 性能に頼る必要があります。

注意:もしテーブルにエイリアスを付けるなら、そのテーブルを参照する時はそのエイリアスを利用しなければいけません。

DELETE t1 FROM test AS t1, test2 WHERE ...

データベース間をまたがる削除は、複合テーブル削除にサポートされていますが、この場合は、エイリアスを使わずにテーブルを参照する必要があります。例:

DELETE test1.tmp1, test2.tmp2 FROM test1.tmp1, test2.tmp2 WHERE ...

現在は、サブクエリの中で1つのテーブルから削除し、同じテーブルから選択する事はできません。