Как удалить из нескольких таблиц в MySQL?


117

Пытаюсь удалить сразу из нескольких таблиц. Я провел небольшое исследование и пришел к следующему

DELETE FROM `pets` p,
            `pets_activities` pa
      WHERE p.`order` > :order
        AND p.`pet_id` = :pet_id
        AND pa.`id` = p.`pet_id`

Однако я получаю эту ошибку

Uncaught Database_Exception [1064]: у вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис рядом с 'p, pets_activitiespa ...

Я никогда раньше не выполнял удаление кросс-таблицы, поэтому у меня нет опыта и я застрял!

Что я делаю не так?

Ответы:


205

Используйте JOINв DELETEзаявлении.

DELETE p, pa
      FROM pets p
      JOIN pets_activities pa ON pa.id = p.pet_id
     WHERE p.order > :order
       AND p.pet_id = :pet_id

В качестве альтернативы вы можете использовать ...

DELETE pa
      FROM pets_activities pa
      JOIN pets p ON pa.id = p.pet_id
 WHERE p.order > :order
   AND p.pet_id = :pet_id

... удалить только из pets_activities

Смотрите это .

Для одиночных удалений таблицы, но с ссылочной целостности, есть и другие способы сделать с EXISTS, NOT EXISTS, IN, NOT INи т.д. Но один выше , где вы указываете , из которых таблицы для удаления с псевдонимом , прежде чем FROMположение вы можете получить из нескольких довольно плотно пятна легче. Я обычно обращаюсь к нему EXISTSв 99% случаев, а затем есть 1%, когда этот синтаксис MySQL занимает день.


7
Я попробовал этот запрос «удалить все в 1» с объединением 6 больших таблиц (каждая около 15 тыс. Строк), и запрос занял 155 секунд, чтобы удалить 63 строки в 6 таблицах: O
Клемен Тушар

1
@cadman Это действительно правильный ответ; могут быть аргументы против его использования, но иногда он очень полезен
Саймон Кристиан

1
+1 Я согласен с тем, что это действительно правильный ответ, поскольку вопрос был не в том, «стоит ли», а в том, «как». Однако мне было бы интересно услышать об 1%, потому что я не могу придумать ни одной ситуации, когда это было бы предпочтительнее.
Эрик Робертсон

2
@techouse, вы присоединились и отфильтровали по индексам? 15k x 15k x 15k x 15k 15k x 15k - это 11 миллионов. Это SELECTзаняло столько же времени?
Пол Дрейпер

6
Вы также можете использовать LEFT JOIN, что полезно, если во второй таблице нет соответствующих записей, иначе ничего не будет удалено.
Lexib0y

20

Поскольку это кажется простыми отношениями родитель / потомок между petsи pets_activities, вам лучше создать ограничение внешнего ключа с помощью каскада удаления.

Таким образом, когда petsстрока удаляется, pets_activitiesсвязанные с ней строки также автоматически удаляются.

Тогда ваш запрос станет простым:

delete from `pets`
    where `order` > :order
      and `pet_id` = :pet_id

3
@Erick, при условии, что вы настроили ссылочную целостность, каскадное удаление может вызвать не больше проблем, чем удаление само по себе. Мы уже знаем, что paэто правильный дочерний элемент из- pза id/pet_idсопоставления.
paxdiablo

14
Что ж, у вас, ребята, есть свои мысли, но похоже, что вы сильно сбрасываете со счетов возможности СУБД ». Каскадное удаление является такой же частью управления данными, как триггеры, хранимые процедуры или ограничения, и они опасны, только если вы не знаете, что делаете. Тем не менее, я не буду спорить дальше, нам просто нужно согласиться, чтобы не соглашаться.
paxdiablo

8
Эрик, теперь ты пробудил мой интерес. Как обеспечить целостность данных в базе данных без ограничений?
paxdiablo

4
@Erick сказал: «Я также не использую триггеры, хранимые процедуры или ограничения». Ах, вы используете Excel. :-)
james.garriss

4
Я просто хочу следить за этим. Я изменил свою позицию по поводу удаления каскадов в этой ситуации. Я был частью новой среды SQL, которая их использовала, и использовал их хорошо, и они были очень организованы. В этой системе наличие этих каскадов оказалось очень полезным для нас. Это определенно предотвратило потерю данных и не было опасным. Проблема в том, что каждый, кто работает с базой данных, должен понимать, как их безопасно использовать. Но всегда есть риски, когда младшие разработчики вносят изменения в базу данных без присмотра.
Эрик Робертсон

14

Использовать это

DELETE FROM `articles`, `comments` 
USING `articles`,`comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

или

DELETE `articles`, `comments` 
FROM `articles`, `comments` 
WHERE `comments`.`article_id` = `articles`.`id` AND `articles`.`id` = 4

1
Нашел хорошую ссылку для использования этого и нескольких других вариантов на mysqltutorial.org/mysql-delete-statement.aspx
Mavelo

3

В настоящий момент у меня нет базы данных mysql для тестирования, но пробовали ли вы указать, что следует удалить до предложения from? Например:

DELETE p, pa FROM `pets` p,
        `pets_activities` pa
  WHERE p.`order` > :order
    AND p.`pet_id` = :pet_id
    AND pa.`id` = p.`pet_id`

Я думаю, что используемый вами синтаксис ограничен более новыми версиями mysql.


1
Этот запрос выполнен успешно, однако он не удалил ни одной строки (но я считаю, что должен).
Alex

2

Синтаксис мне кажется правильным ... попробуйте изменить его, чтобы использовать INNER JOIN...

Посмотри на это .


7
Жаль, что вы не включили фактическое решение, потому что ссылка верна!
mycroes

1

Для всех, кто читал это в 2017 году, я сделал нечто подобное.

DELETE pets, pets_activities FROM pets inner join pets_activities
on pets_activities.id = pets.id WHERE pets.`order` > :order AND 
pets.`pet_id` = :pet_id

Как правило, для удаления строк из нескольких таблиц ниже приведен синтаксис, которому я следую. Решение основано на предположении, что между двумя таблицами существует некоторая связь.

DELETE table1, table2 FROM table1 inner join table2 on table2.id = table1.id
WHERE [conditions]

1

Я нашел эту статью, в которой показано, как удалить данные из нескольких таблиц с помощью оператора MySQL DELETE JOIN с хорошим объяснением.

введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.