2013-06-13 2 views
4

У меня есть таблица, называемая элементами с столбцами «itemID» и «parentID», где parentID - это идентификатор из другой строки в таблице. Я хочу удалить строки, где parentID-строка больше не существует.Mysql удалить строку, где родитель не существует

Это то, что я придумал:

DELETE FROM items 
WHERE (SELECT COUNT(1) 
     FROM items as parent 
     WHERE items.parentID=parent.itemID)=0 

Но я получаю следующее сообщение об ошибке: Вы не можете указать целевые таблицы «элементов» для обновления в ЕКЕ

EDIT: его было бы неплохо, если бы элементы, связанные с элементами, удаленными этим запросом, также были удалены по запросу, возможно ли это в sql или я должен его закодировать?

ответ

6

Использование подзапросов неэффективно; использовать левое соединение с multiple-table syntax:

DELETE items 
FROM items 
    left join items as parent 
     on items.parentID = parent.itemID 
WHERE parent.itemID is NULL 

синтаксис многотабличные позволяет указать присоединиться к команде удаления - так что вы можете объединить несколько таблиц и удалять только из одного. То есть DELETE t1 FROM t1 join t2 .... присоединяется к t1 и t2, но удаляет только соответствующие строки из таблицы t1.

Что касается вашего вопроса «было бы хорошо, если бы элементы, связанные с элементами, удаленными по этому запросу, также были удалены по запросу, возможно ли это в sql или я должен его закодировать?»

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

Таким образом, я думаю, что самое легкое решение - повторить предыдущий запрос до тех пор, пока строки не будут удалены.

+0

Спасибо, это работает отлично! Я напишу функцию, которая повторно запускается до тех пор, пока не удастся удалить больше элементов. – user2481664

2

Запрос будет

DELETE items FROM items 
left join parent 
    on items.parentID = parent.ID 
WHERE parent.ID is NULL 
+1

не будет работать, потому что удаление должно знать, из какой таблицы удалить. Вам нужно использовать синтаксис muultiple-table, см. Мой ответ. – TMS

+0

@ Томас Спасибо за исправление. :) –

+0

YogeshSuthar, добро пожаловать :-) – TMS

0

попробовать это маленькое колдовство ...

delete from FooTable f1 where f1.parent_id 
     not in (select f2.item_id from FooTable f2); 

конечно этот запрос имеет небольшую проблему, если вы шулер вы, вероятно, заметили, что это может генерировать новые FooRecords без родителя (это значит, что их родитель может быть удален во время выполнения запроса).

выполнить запрос несколько раз вручную, если вам не нужно что-то автоматизировать, или поместить ее в петлю и остановить цикл, когда число удаленных записей 0.

Смежные вопросы