DELETE в MySQL — 100 жизненных приёмов и уникальных кейсов

100 уникальных кейсов MySQL DELETE: условия, JOIN, LIMIT, транзакции, JSON, партиции, безопасность.

🟢 DELETE в MySQL. Введение

DELETE в MySQL — оператор удаления строк из таблиц. Поддерживает условия фильтрации, многотабличные удаления через JOIN, ограничения ORDER BY/LIMIT, работу в транзакциях, а также взаимодействие с внешними ключами. DELETE применяют для точечного и массового очищения данных, подготовки архивов и поддержания целостности.

Ниже — краткий синтаксис и затем 100 уникальных примеров из практики (разные домены и приёмы).

Синтаксис

DELETE FROM tbl WHERE condition;
DELETE t1 FROM t1 JOIN t2 ON t1.key=t2.key WHERE predicate;
DELETE FROM tbl ORDER BY some_col LIMIT n;
DELETE FROM tbl WHERE id IN (SELECT id FROM other_tbl);
START TRANSACTION; DELETE FROM tbl WHERE cond; COMMIT;

Типовая конструкция

DELETE FROM sessions WHERE user_id=42 AND expires_at<NOW();

100 примеров

1. Удаление неактивных сессий старше недели

DELETE FROM sessions WHERE last_seen<NOW()-INTERVAL 7 DAY;

2. Очистка неподтверждённых аккаунтов

DELETE FROM users WHERE email_verified=0 AND created_at<NOW()-INTERVAL 3 DAY;

3. Удаление просроченных одноразовых токенов

DELETE FROM auth_tokens WHERE kind='otp' AND expires_at<NOW();

4. Сброс приглашений без регистрации

DELETE FROM invites WHERE accepted_at IS NULL AND created_at<CURDATE()-INTERVAL 30 DAY;

5. Удаление банов с истёкшим сроком

DELETE FROM bans WHERE until_at<NOW();

6. Очистка корзин без позиций

DELETE FROM carts c WHERE NOT EXISTS(SELECT 1 FROM cart_items i WHERE i.cart_id=c.id);

7. Удаление черновых заказов без оплаты

DELETE FROM orders WHERE status='draft' AND NOT EXISTS(SELECT 1 FROM payments p WHERE p.order_id=orders.id);

8. Удаление устаревших купонов

DELETE FROM coupons WHERE active=0 AND updated_at<CURDATE()-INTERVAL 180 DAY;

9. Снос временных позиций корзины по маске SKU

DELETE FROM cart_items WHERE sku LIKE 'TMP-%';

10. Удаление пустых категорий

DELETE FROM categories c WHERE NOT EXISTS(SELECT 1 FROM products p WHERE p.category_id=c.id);

11. Удаление спама в комментариях по REGEXP

DELETE FROM comments WHERE body REGEXP '(?i)buy now|free crypto|casino';

12. Очистка черновиков без заголовка

DELETE FROM posts WHERE status='draft' AND TRIM(title)='';

13. Удаление старых ревизий страниц

DELETE FROM page_revisions WHERE created_at<CURDATE()-INTERVAL 90 DAY;

14. Снос неиспользуемых тегов

DELETE FROM tags t WHERE NOT EXISTS(SELECT 1 FROM post_tags pt WHERE pt.tag_id=t.id);

15. Удаление невалидных ссылок

DELETE FROM links WHERE url NOT REGEXP '^(https?)://';

16. Очистка логов старше 90 дней

DELETE FROM logs WHERE created_at<CURDATE()-INTERVAL 90 DAY;

17. Удаление дубликатов логов по ключу

DELETE l1 FROM logs l1 JOIN logs l2 ON l1.hash=l2.hash AND l1.id>l2.id;

18. Удаление технических отладочных записей

DELETE FROM logs WHERE level='debug' AND created_at<CURDATE()-INTERVAL 7 DAY;

19. Снос шумных heartbeat-событий

DELETE FROM events WHERE type='heartbeat' AND created_at<CURDATE()-INTERVAL 1 DAY;

20. Удаление пустых payload в событиях

DELETE FROM events WHERE JSON_EXTRACT(payload,'$.data') IS NULL;

Еще 20 примеров

21. Очистка стейджинга после загрузки

DELETE FROM stage_orders WHERE loaded=1;

22. Удаление семпла старшего, чем N дней

DELETE FROM sample WHERE sampled_at<CURDATE()-INTERVAL 14 DAY;

23. Снос временных агрегаций

DELETE FROM agg_temp WHERE batch_id IN (SELECT id FROM batches WHERE finished=1);

24. Удаление дубликатных ключей в витрине

DELETE t1 FROM mart_daily t1 JOIN mart_daily t2 ON t1.d=t2.d AND t1.id>t2.id;

25. Очистка промежуточных join-таблиц

DELETE FROM tmp_join_data;

26. Удаление отменённых транзакций без проводок

DELETE FROM tx WHERE status='cancelled' AND NOT EXISTS(SELECT 1 FROM ledger l WHERE l.tx_id=tx.id);

27. Снос пустых счетов

DELETE FROM accounts a WHERE a.balance=0 AND NOT EXISTS(SELECT 1 FROM transactions t WHERE t.account_id=a.id);

28. Удаление черновых инвойсов с нулём

DELETE FROM invoices WHERE status='draft' AND total=0;

29. Очистка устаревших курсов валют

DELETE FROM fx WHERE date<CURDATE()-INTERVAL 365 DAY AND source<>'ECB';

30. Удаление тестовых платежей

DELETE FROM payments WHERE note LIKE '%TEST%' OR user_id=0;

31. Снос нулевых остатков с давней датой

DELETE FROM stock WHERE qty=0 AND updated_at<CURDATE()-INTERVAL 60 DAY;

32. Удаление неиспользуемых складов

DELETE w FROM warehouses w LEFT JOIN stock s ON s.warehouse_id=w.id WHERE s.warehouse_id IS NULL;

33. Очистка зарезервированных позиций без заказа

DELETE FROM reservations r WHERE NOT EXISTS(SELECT 1 FROM orders o WHERE o.id=r.order_id);

34. Удаление просроченных резервов

DELETE FROM reservations WHERE expires_at<NOW();

35. Снос дубликатов SKU

DELETE p1 FROM products p1 JOIN products p2 ON p1.sku=p2.sku AND p1.id>p2.id;

36. Удаление старых координат трекинга

DELETE FROM device_track WHERE ts<CURDATE()-INTERVAL 3 DAY;

37. Снос точек вне допустимого диапазона

DELETE FROM geo_points WHERE lat NOT BETWEEN -90 AND 90 OR lng NOT BETWEEN -180 AND 180;

38. Очистка геокэша по таймауту


DELETE FROM geocache WHERE cached_at<CURDATE()-INTERVAL 30 DAY;

39. Удаление шумовых данных датчика


DELETE FROM sensor_data WHERE value IS NULL OR value=0;

40. Снос пустых гео-кластеров


DELETE c FROM clusters c LEFT JOIN points p ON p.cluster_id=c.id WHERE p.id IS NULL;

Еще 20 примеров

41. Удаление bounce‑адресов

DELETE FROM emails WHERE status='bounce' AND updated_at<CURDATE()-INTERVAL 90 DAY;

42. Очистка очереди отправленных писем

DELETE FROM outbox WHERE sent_at IS NOT NULL AND sent_at<CURDATE()-INTERVAL 7 DAY;

43. Снос отписавшихся из рассылки

DELETE FROM subscribers WHERE unsubscribed=1;

44. Удаление сообщений чата старше N

DELETE FROM chat_msgs WHERE created_at<CURDATE()-INTERVAL 30 DAY;

45. Снос пустых чатов

DELETE c FROM chats c LEFT JOIN chat_msgs m ON m.chat_id=c.id WHERE m.id IS NULL;

46. Удаление устаревших попыток входа

DELETE FROM login_attempts WHERE created_at<CURDATE()-INTERVAL 1 DAY;

47. Снос просроченных recovery‑токенов

DELETE FROM recovery_tokens WHERE expires_at<NOW();

48. Очистка таблицы блокировок

DELETE FROM locks WHERE released=1 OR expires_at<NOW();

49. Удаление устаревших ACL правил

DELETE FROM acl WHERE valid_to<NOW();

50. Снос подозрительных IP по списку

DELETE FROM ip_blacklist WHERE ip IN ('0.0.0.0','127.0.0.1');

51. Удаление нефотографических аватаров

DELETE FROM avatars WHERE mime_type NOT LIKE 'image/%';

52. Снос неиспользуемых альбомов

DELETE a FROM albums a LEFT JOIN photos p ON p.album_id=a.id WHERE p.id IS NULL;

53. Очистка загруженных, но не привязанных файлов

DELETE FROM uploads u WHERE u.post_id IS NULL AND u.created_at<CURDATE()-INTERVAL 14 DAY;

54. Удаление пустых биографий

DELETE FROM profiles WHERE TRIM(bio)='';

55. Снос дубликатов подписок

DELETE s1 FROM subscriptions s1 JOIN subscriptions s2 ON s1.user_id=s2.user_id AND s1.target_id=s2.target_id AND s1.id>s2.id;

56. Удаление конфигов без обязательного ключа

DELETE FROM cfg WHERE JSON_EXTRACT(body,'$.required') IS NULL;

57. Снос устаревших версий конфигов

DELETE FROM cfg WHERE JSON_EXTRACT(body,'$.ver')<2;

58. Очистка пустых массивов в метаданных

DELETE FROM user_meta WHERE JSON_CONTAINS(prefs,'[]');

59. Удаление конфигов определённой темы

DELETE FROM cfg WHERE JSON_EXTRACT(body,'$.theme')='old';

60. Снос «битых» JSON строк

DELETE FROM json_store WHERE body REGEXP '^[^{\[]';

Еще 20 примеров

61. Очистка кеша

DELETE FROM cache WHERE expires_at<NOW() OR cval IS NULL;

62. Удаление временных таблиц отчётов

DELETE FROM report_tmp WHERE created_at<CURDATE()-INTERVAL 3 DAY;

63. Снос очереди заданий в статусе done

DELETE FROM jobs WHERE status='done' AND finished_at<CURDATE()-INTERVAL 7 DAY;

64. Удаление «висячих» записей связей

DELETE r FROM relations r LEFT JOIN entities e ON e.id=r.entity_id WHERE e.id IS NULL;

65. Очистка таблицы нотификаций

DELETE FROM notifications WHERE read_at IS NOT NULL AND read_at<CURDATE()-INTERVAL 30 DAY;

66. Удаление записей прошлых партиций

DELETE FROM sales WHERE created_at<'2025-01-01';

67. Очистка партиции месяца

DELETE FROM sales WHERE created_at BETWEEN '2025-08-01' AND '2025-08-31';

68. Снос лишних записей оставляя топ‑N по сумме

DELETE FROM orders WHERE id NOT IN (SELECT id FROM (SELECT id FROM orders ORDER BY total DESC LIMIT 100) t);

69. Удаление дублей, оставляя минимальный id

DELETE u1 FROM users u1 JOIN users u2 ON u1.email=u2.email AND u1.id>u2.id;

70. Снос хвоста очереди по ORDER/LIMIT

DELETE FROM queue ORDER BY created_at ASC LIMIT 1000;

71. Удаление комментариев к удаляемым постам (JOIN)

DELETE c FROM comments c JOIN posts p ON p.id=c.post_id WHERE p.status='deleted';

72. Снос item’ов сирот (LEFT JOIN)

DELETE i FROM order_items i LEFT JOIN orders o ON o.id=i.order_id WHERE o.id IS NULL;

73. Удаление связей many-to-many без объекта

DELETE pt FROM post_tags pt LEFT JOIN posts p ON p.id=pt.post_id WHERE p.id IS NULL;

74. Удаление зависимых адресов клиента

DELETE a FROM addresses a JOIN customers c ON c.id=a.customer_id WHERE c.deleted=1;

75. Снос черновых платежей без инвойса

DELETE p FROM payments p LEFT JOIN invoices i ON i.id=p.invoice_id WHERE i.id IS NULL;

76. Удаление с IGNORE уникальных конфликтов

DELETE IGNORE FROM tmp_unique WHERE flag=1;

77. Снос записей по списку id

DELETE FROM items WHERE id IN (10,20,30,40);

78. Удаление по подзапросу наличия

DELETE FROM devices d WHERE EXISTS(SELECT 1 FROM device_errors e WHERE e.device_id=d.id);

79. Снос по диапазону дат

DELETE FROM logs WHERE created_at BETWEEN '2025-01-01' AND '2025-01-31';

80. Удаление записи по составному ключу

DELETE FROM stock WHERE warehouse_id=1 AND sku='A-1';

Еще 20 примеров

81. Очистка аккумулируемых метрик

DELETE FROM metrics WHERE day<CURDATE()-INTERVAL 365 DAY;

82. Удаление NaN/inf суррогатов

DELETE FROM measures WHERE val IN ('NaN','Infinity');

83. Снос записей с недопустимым email

DELETE FROM users WHERE email NOT REGEXP '^[^@\s]+@[^@\s]+\.[^@\s]+$';

84. Удаление телефонов без цифр

DELETE FROM phones WHERE REGEXP_REPLACE(raw,'[^0-9]+','')='';

85. Снос некорректной валюты

DELETE FROM invoices WHERE ccy NOT IN ('USD','EUR','GBP');

86. Удаление строк после архивации

DELETE FROM orders WHERE archived=1;

87. Снос старых архивов превышающих лимит

DELETE FROM archives WHERE kind='daily' AND created_at<CURDATE()-INTERVAL 60 DAY;

88. Очистка staging после MERGE

DELETE FROM staging_users WHERE merged=1;

89. Удаление копий‑дубликатов архивов

DELETE a1 FROM archives a1 JOIN archives a2 ON a1.hash=a2.hash AND a1.id>a2.id;

90. Снос устаревших экспортов

DELETE FROM exports WHERE finished_at<CURDATE()-INTERVAL 14 DAY;

91. Удаление персональных данных по запросу

DELETE FROM personal_data WHERE request_id=?;

92. Снос логов трекинга для пользователя

DELETE FROM tracking WHERE user_id=?;

93. Удаление геоданных по региону

DELETE FROM geodata WHERE region='EU' AND consent=0;

94. Очистка писем с ПД при отзыве согласия

DELETE FROM attachments WHERE contains_pi=1 AND user_id IN (SELECT id FROM users WHERE consent=0);

95. Снос профилей после срока хранения

DELETE FROM profiles WHERE deleted_at<CURDATE()-INTERVAL 30 DAY;

96. Удаление в транзакции: заказы + платежи

START TRANSACTION; DELETE FROM payments WHERE order_id IN (SELECT id FROM orders WHERE status='cancelled'); DELETE FROM orders WHERE status='cancelled'; COMMIT;

97. Откат тестовой очистки

START TRANSACTION; DELETE FROM sandbox WHERE tag='tmp'; ROLLBACK;

98. Удаление с фиксацией в аудите

START TRANSACTION; DELETE FROM items WHERE obsolete=1; INSERT INTO audit(event,created_at) VALUES('cleanup',NOW()); COMMIT;

99. Удаление с блокировкой строки

START TRANSACTION; SELECT * FROM settings WHERE id=1 FOR UPDATE; DELETE FROM settings WHERE id=1; COMMIT;

100. Пакетная очистка с LIMIT порциями

DELETE FROM temp_data ORDER BY id LIMIT 1000;

Заключение

DELETE в MySQL — базовый инструмент очистки данных. Он позволяет удалять строки выборочно и массово, с условиями, через JOIN и подзапросы, контролировать порядок и объём через ORDER BY/LIMIT, использовать транзакции и поддерживать целостность. Примеры выше охватывают реальные кейсы из разных доменов.

Подробнее — в официальной документации MySQL.


 

Понравилась статья? Поделиться с друзьями: