13.2.2 DELETE Statement
DELETE is a DML statement that removes rows from a table.
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [PARTITION (partition_name [, partition_name] ...)] [WHERE where_condition] [ORDER BY ...] [LIMIT row_count]
DELETE statement deletes rows from
tbl_name and returns the number of deleted rows. To check the number of deleted rows, call the
ROW_COUNT() function described in Section 12.15, “Information Functions”.
The conditions in the optional
WHERE clause identify which rows to delete. With no
WHERE clause, all rows are deleted.
where_condition is an expression that evaluates to true for each row to be deleted. It is specified as described in Section 13.2.9, “SELECT Statement”.
ORDER BY clause is specified, the rows are deleted in the order that is specified. The
LIMIT clause places a limit on the number of rows that can be deleted. These clauses apply to single-table deletes, but not multi-table deletes.
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]
When you do not need to know the number of deleted rows, the
TRUNCATE TABLE statement is a faster way to empty a table than a
DELETE statement with no
WHERE clause. Unlike
TRUNCATE TABLE cannot be used within a transaction or if you have a lock on the table. See Section 13.1.34, “TRUNCATE TABLE Statement” and Section 13.3.5, “LOCK TABLES and UNLOCK TABLES Statements”.
The speed of delete operations may also be affected by factors discussed in Section 126.96.36.199, “Optimizing DELETE Statements”.
To ensure that a given
DELETE statement does not take too much time, the MySQL-specific
LIMIT clause for
DELETE specifies the maximum number of rows to be deleted. If the number of rows to delete is larger than the limit, repeat the
DELETE statement until the number of affected rows is less than the
You cannot delete from a table and select from the same table in a subquery.
DELETE supports explicit partition selection using the
PARTITION option, which takes a list of the comma-separated names of one or more partitions or subpartitions (or both) from which to select rows to be dropped. Partitions not included in the list are ignored. Given a partitioned table
t with a partition named
p0, executing the statement
DELETE FROM t PARTITION (p0) has the same effect on the table as executing
ALTER TABLE t TRUNCATE PARTITION (p0); in both cases, all rows in partition
p0 are dropped.
PARTITION can be used along with a
WHERE condition, in which case the condition is tested only on rows in the listed partitions. For example,
DELETE FROM t PARTITION (p0) WHERE c < 5 deletes rows only from partition
p0 for which the condition
c < 5 is true; rows in any other partitions are not checked and thus not affected by the
PARTITION option can also be used in multiple-table
DELETE statements. You can use up to one such option per table named in the
For more information and examples, see Section 22.5, “Partition Selection”.
If you delete the row containing the maximum value for an
AUTO_INCREMENT column, the value is not reused for a
InnoDB table. If you delete all rows in the table with
DELETE FROM (without a
WHERE clause) in
autocommit mode, the sequence starts over for all storage engines except
MyISAM. There are some exceptions to this behavior for
InnoDB tables, as discussed in Section 188.8.131.52, “AUTO_INCREMENT Handling in InnoDB”.
MyISAM tables, you can specify an
AUTO_INCREMENT secondary column in a multiple-column key. In this case, reuse of values deleted from the top of the sequence occurs even for
MyISAM tables. See Section 3.6.9, “Using AUTO_INCREMENT”.
DELETE statement supports the following modifiers:
If you specify the
LOW_PRIORITYmodifier, the server delays execution of the
DELETEuntil no other clients are reading from the table. This affects only storage engines that use only table-level locking (such as
MyISAMtables, if you use the
QUICKmodifier, the storage engine does not merge index leaves during delete, which may speed up some kinds of delete operations.
IGNOREmodifier causes MySQL to ignore errors during the process of deleting rows. (Errors encountered during the parsing stage are processed in the usual manner.) Errors that are ignored due to the use of
IGNOREare returned as warnings. For more information, see Comparison of the IGNORE Keyword and Strict SQL Mode.
DELETE statement includes an
ORDER BY clause, rows are deleted in the order specified by the clause. This is useful primarily in conjunction with
LIMIT. For example, the following statement finds rows matching the
WHERE clause, sorts them by
timestamp_column, and deletes the first (oldest) one:
DELETE FROM somelog WHERE user = 'jcole' ORDER BY timestamp_column LIMIT 1;
ORDER BY also helps to delete rows in an order required to avoid referential integrity violations.
If you are deleting many rows from a large table, you may exceed the lock table size for an
InnoDB table. To avoid this problem, or simply to minimize the time that the table remains locked, the following strategy (which does not use
DELETE at all) might be helpful:
Select the rows not to be deleted into an empty table that has the same structure as the original table:
INSERT INTO t_copy SELECT * FROM t WHERE ... ;
RENAME TABLEto atomically move the original table out of the way and rename the copy to the original name:
RENAME TABLE t TO t_old, t_copy TO t;
Drop the original table:
DROP TABLE t_old;
MyISAM tables, deleted rows are maintained in a linked list and subsequent
INSERT operations reuse old row positions. To reclaim unused space and reduce file sizes, use the
OPTIMIZE TABLE statement or the myisamchk utility to reorganize tables.
OPTIMIZE TABLE is easier to use, but myisamchk is faster. See Section 184.108.40.206, “OPTIMIZE TABLE Statement”, and Section 4.6.3, “myisamchk — MyISAM Table-Maintenance Utility”.
QUICK modifier affects whether index leaves are merged for delete operations.
DELETE QUICK is most useful for applications where index values for deleted rows are replaced by similar index values from rows inserted later. In this case, the holes left by deleted values are reused.
DELETE QUICK is not useful when deleted values lead to underfilled index blocks spanning a range of index values for which new inserts occur again. In this case, use of
QUICK can lead to wasted space in the index that remains unreclaimed. Here is an example of such a scenario:
In this scenario, the index blocks associated with the deleted index values become underfilled but are not merged with other index blocks due to the use of
QUICK. They remain underfilled when new inserts occur, because new rows do not have index values in the deleted range. Furthermore, they remain underfilled even if you later use
QUICK, unless some of the deleted index values happen to lie in index blocks within or adjacent to the underfilled blocks. To reclaim unused index space under these circumstances, use
If you are going to delete many rows from a table, it might be faster to use
DELETE QUICK followed by
OPTIMIZE TABLE. This rebuilds the index rather than performing many index block merge operations.
You can specify multiple tables in a
DELETE statement to delete rows from one or more tables depending on the condition in the
WHERE clause. You cannot use
ORDER BY or
LIMIT in a multiple-table
table_references clause lists the tables involved in the join, as described in Section 220.127.116.11, “JOIN Clause”.
For the first multiple-table syntax, only matching rows from the tables listed before the
FROM clause are deleted. For the second multiple-table syntax, only matching rows from the tables listed in the
FROM clause (before the
USING clause) are deleted. The effect is that you can delete rows from many tables at the same time and have additional tables that are used only for searching:
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;
These statements use all three tables when searching for rows to delete, but delete matching rows only from tables
The preceding examples use
INNER JOIN, but multiple-table
DELETE statements can use other types of join permitted in
SELECT statements, such as
LEFT JOIN. For example, to delete rows that exist in
t1 that have no match in
t2, use a
DELETE t1 FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
The syntax permits
.* after each
tbl_name for compatibility with Access.
If you use a multiple-table
DELETE statement involving
InnoDB tables for which there are foreign key constraints, the MySQL optimizer might process tables in an order that differs from that of their parent/child relationship. In this case, the statement fails and rolls back. Instead, you should delete from a single table and rely on the
ON DELETE capabilities that
InnoDB provides to cause the other tables to be modified accordingly.
If you declare an alias for a table, you must use the alias when referring to the table:
DELETE t1 FROM test AS t1, test2 WHERE ...
Table aliases in a multiple-table
DELETE should be declared only in the
table_references part of the statement. Elsewhere, alias references are permitted but not alias declarations.
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;