В MySQL я хочу удалить строки в таблице t1 и все связанные строки в таблице t2, где выполняется какое-либо условие (например, некоторый статус).Использование нескольких DELETE в MySQL вместо JOIN DELETE
Я знаю, что могу это сделать:
DELETE t1 FROM t1 INNER JOIN t2
WHERE t1.some_id = t2.some_id
AND t1.status=3;
Но есть некоторые повисшие данные в t2, не ссылается t1, и я хочу, чтобы удалить это тоже (это и старый разбитый DB). Я думаю, что я мог бы сделать внешнее соединение для этого, а UNION - с внутренним соединением. Но это становится более сложным, потому что мне нужно удалить строки примерно в 10 таблицах, все связанные с идентификаторами. Конечным результатом был сумасшедший большой запрос.
Так что я привел в этом:
DELETE FROM t1
WHERE status=3;
DELETE FROM t2
WHERE some_id NOT IN (SELECT some_ID FROM t1)
DELETE FROM t3
WHERE some_id NOT IN (SELECT some_ID FROM t2)
и так далее для всех таблиц. Таким образом, все несвязанные данные удаляются, и это более читаемо. Обратите внимание, что внешних ключей нет, и я не могу изменять таблицы (так что забудьте о «каскадном удалении»).
Итак, это неправильно? Каковы недостатки этого, как я это сделал?
Благодаря
Edit: таблицы большие, t1 имеет полтора миллиона строк, t2 имеет 3 миллионы строк, в 8 других таблицах менее полторы миллионов. Но я также удаляю много данных, около 75%.
Редактировать 2: Хорошо, я покажу вам настоящую вещь, а не только пример. Целью этого является удаление около 250000 старых билетов в osTicket (после их резервного копирования).
Работа в виртуальной машине, я сначала попытался это:
DELETE ticket, thread, event, cdata, user, email, email_info
FROM ost_ticket AS ticket
INNER JOIN ost_ticket_thread AS thread
INNER JOIN ost_ticket_event AS event
INNER JOIN ost_ticket__cdata AS cdata
INNER JOIN ost_user AS user
INNER JOIN ost_user_email AS email
INNER JOIN ost_ticket_email_info AS email_info
WHERE ticket.ticket_id = thread.ticket_id
AND ticket.ticket_id = event.ticket_id
AND ticket.ticket_id = cdata.ticket_id
AND ticket.user_id = user.id
AND ticket.user_id = email.user_id
AND thread.id = email_info.thread_id
AND ticket.status_id=3
AND (ticket.closed < DATE_SUB(NOW(), INTERVAL 30 DAY));
Это удаляет только 7 таблиц, мне нужно добавить по крайней мере, 2-3 таблицы к нему. Может больше. Это займет 15 минут, чтобы запустить и оставляет много несвязанных данных.
Тогда я пошел с этим (в обновленном VM)
START TRANSACTION;
DELETE FROM ost_ticket WHERE status_id=3 AND (closed < DATE_SUB(NOW(), INTERVAL 30 DAY));
DELETE FROM ost_ticket_thread WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_ticket_event WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_ticket__cdata WHERE ticket_id NOT IN (SELECT ticket_id FROM ost_ticket);
DELETE FROM ost_user WHERE id NOT IN (SELECT DISTINCT user_id FROM ost_ticket);
DELETE FROM ost_user_email WHERE user_id NOT IN (SELECT id FROM ost_user);
DELETE FROM ost_ticket_email_info WHERE thread_id NOT IN (SELECT id FROM ost_ticket_thread);
COMMIT;
Он принимает все данные, и занимает 8 минут, чтобы бежать.
Единственный недостаток, который приходит на ум, заключается в том, что вы не делаете это как атомную транзакцию, если это имеет значение. Учитывая, что возраст/состояние базы данных звучит так, как целостность транзакции не производится или не прерывается. Возможно, у других есть идеи. – mba12
Я не вижу проблемы с этим. – CptMisery
Имеются удаления нескольких таблиц. [docs] (http://dev.mysql.com/doc/refman/5.7/en/delete.html) – Uueerdo