Search the MySQL manual:
Subscribe to the monthly
MySQL Newsletter!

6.4.6 Синтаксис оператора DELETE

DELETE [LOW_PRIORITY] [QUICK] FROM table_name
       [WHERE where_definition]
       [ORDER BY ...]
       [LIMIT rows]

или

DELETE [LOW_PRIORITY] [QUICK] table_name[.*] [, table_name[.*] ...]
       FROM table-references
       [WHERE where_definition]

или

DELETE [LOW_PRIORITY] [QUICK]
       FROM table_name[.*] [, table_name[.*] ...]
       USING table-references
       [WHERE where_definition]

Оператор DELETE удаляет из таблицы table_name строки, удовлетворяющие заданным в where_definition условиям, и возвращает число удаленных записей.

Если оператор DELETE запускается без определения WHERE, то удаляются все строки. При работе в режиме AUTOCOMMIT это будет аналогично использованию оператора TRUNCATE. See section 6.4.7 Синтаксис оператора TRUNCATE. В MySQL 3.23 оператор DELETE без определения WHERE возвратит ноль как число удаленных записей.

Если действительно необходимо знать число удаленных записей при удалении всех строк, и если допустимы потери в скорости, то можно использовать команду DELETE в следующей форме:

mysql> DELETE FROM table_name WHERE 1>0;

Следует учитывать, что эта форма работает намного медленнее, чем DELETE FROM table_name без выражения WHERE, поскольку строки удаляются поочередно по одной.

Если указано ключевое слово LOW_PRIORITY, выполнение данной команды DELETE будет задержано до тех пор, пока другие клиенты не завершат чтение этой таблицы.

Если задан параметр QUICK, то обработчик таблицы при выполнении удаления не будет объединять индексы - в некоторых случаях это может ускорить данную операцию.

В таблицах MyISAM удаленные записи сохраняются в связанном списке, а последующие операции INSERT повторно используют места, где располагались удаленные записи. Чтобы возвратить неиспользуемое пространство и уменьшить размер файлов, можно применить команду OPTIMIZE TABLE или утилиту myisamchk для реорганизации таблиц. Команда OPTIMIZE TABLE проще, но утилита myisamchk работает быстрее. See section 4.5.1 Синтаксис команды OPTIMIZE TABLE. See section 4.4.6.10 Оптимизация таблиц.

Первый из числа приведенных в начале данного раздела многотабличный формат команды DELETE поддерживается, начиная с MySQL 4.0.0. Второй многотабличный формат поддерживается, начиная с MySQL 4.0.2.

Идея заключается в том, что удаляются только совпадающие строки из таблиц, перечисленных перед выражениями FROM или USING. Это позволяет удалять единовременно строки из нескольких таблиц, а также использовать для поиска дополнительные таблицы.

Символы .* после имен таблиц требуются только для совместимости с Access:

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

В предыдущем случае просто удалены совпадающие строки из таблиц t1 и t2.

Если применяется выражение ORDER BY (доступно с версии MySQL 4.0), то строки будут удалены в указанном порядке. В действительности это выражение полезно только в сочетании с LIMIT. Например:

DELETE FROM somelog
        WHERE user = 'jcole'
        ORDER BY timestamp
        LIMIT 1

Данный оператор удалит самую старую запись (по timestamp), в которой строка соответствует указанной в выражении WHERE.

Специфическая для MySQL опция LIMIT для команды DELETE указывает серверу максимальное количество строк, которые следует удалить до возврата управления клиенту. Эта опция может использоваться для гарантии того, что данная команда DELETE не потребует слишком много времени для выполнения. Можно просто повторять команду DELETE до тех пор, пока количество удаленных строк меньше, чем величина LIMIT.

С MySQL 4.0 вы можете указать множество таблиц в DELETE чтобы удалить записи из одной таблицы, основываясь на условии по множеству таблиц. Однако, с такой формой оператора DELETE нельзя использовать ORDER BY или LIMIT.

User Comments

Posted by Javi Legido on January 17 2003 1:45pm[Delete] [Edit]

In these section you don't say nothing about the parent - child restrictions (on InnoDB tables), because you cannot delete a parent row only. You have to delete the parent, and child row

Posted by [name withheld] on February 4 2003 8:23am[Delete] [Edit]

When you delete a large portion of a MyISAM table, it may be necessary to run an optimize table job afterwards. When the data file becomes fragmented, or when the key distribution data comes out of sync with reality, then you will see large performance drops. Also, disk space will not be freed until you've run optimize.

These are not really bugs, but limitations that you should be aware of when you start deleting large amounts of data from your tables.

Posted by [name withheld] on January 26 2004 8:14am[Delete] [Edit]

If you would like to delete multiple rows, then use this easy example:

DELETE FROM `table` WHERE `id` IN (142,156,168)

This will delete rows with `id` 142, 156 and 168.

Posted by Chris Rywalt on January 29 2004 8:07am[Delete] [Edit]

I spent an hour or so working out how to delete rows matching a specific SELECT statement which was mildly complex:

SELECT A.* FROM table1 AS A, table1 AS B
WHERE A.username LIKE '%2'
AND A.ID = B.ID
AND A.username <> B.username

(Basically, I had accidentally created two usernames for each ID, the extra username ending in 2. But there were some valid usernames ending in 2 which I didn't want to delete.)

I tried several different approaches to crafting a delete statement to get rid of these, all to no avail. I tried DELETE...WHERE IN...SELECT and DELETE...WHERE...= ANY...SELECT, WHERE EXISTS, and several other variations, all of which looked like they should work according to the manual, but none of which did.

Finally -- hence this comment, so you don't have to jump through my hoops -- my DBA wife and I put together this solution:

CREATE TEMPORARY TABLE tmptable
SELECT A.* FROM table1 AS A, table1 AS B
WHERE A.username LIKE '%2'
AND A.ID = B.ID
AND A.username <> B.username;

DELETE table1 FROM table1
INNER JOIN tmptable
ON table1.username = tmptable.username;

Maybe this isn't the best way to do this, but it worked for me. Hope it helps someone else.

Posted by [name withheld] on February 10 2004 1:58am[Delete] [Edit]

It seems that you cannot use an alias for a table when doing a delete. For example, the following won't work:

DELETE a.* FROM table AS a, table AS b WHERE a.parent=b.child

However, simply changing the alias 'a' fixes this query:

DELETE table.* FROM table, table AS b WHERE table.parent=b.child

It now works as expected. Therefore, it's not the self-join that's the problem, but the use of an alias. This doesn't seem to be explained above.

Posted by [name withheld] on February 14 2004 4:25am[Delete] [Edit]

> If you issue a DELETE with no WHERE clause, all rows are
> deleted. If you do this in AUTOCOMMIT mode, this works as
> TRUNCATE. See section 13.1.9 TRUNCATE Syntax.

Note, however, that TRUNCATE will not work if you have a lock on the table, because a TRUNCATE involves dropping and re-creating the table.

If you do a DELETE with no WHERE clause on a locked table, it seems that MySQL is intelligent enough to realise this, because it still works, even though the equivalent TRUNCATE would not because of the lock. In this case MySQL must not be translating it to a TRUNCATE.

Posted by mike on February 24 2004 6:43am[Delete] [Edit]

>If an ORDER BY clause is used (available from MySQL 4.0.0), >the rows will be deleted in that order. This is really useful >only in conjunction with LIMIT.

Actually that is not the only time it is useful. For one thing, you can use this to make sure that the deletes happened in an order which preserves referential integrity.

If you have a table that has rows which are parents of other rows, and you know that you have created them in such a way that the parent rows are always created before the child rows, you could use the order by in your delete to get the child rows first.


mysql> delete from account where 1>0;
ERROR 1217: Cannot delete or update a parent row: a foreign key constraint fails
mysql> select * from account;

+----+-----------+------+
| id | parent_id | name |
+----+-----------+------+
| 1 | NULL | mike |
| 2 | 1 | reid |
| 3 | 1 | cole |
+----+-----------+------+
3 rows in set (0.00 sec)

mysql> delete from account where 1>0 order by id desc;
Query OK, 3 rows affected (0.04 sec)


Add your own comment.