Каков общепринятый метод удаления записей, на которые ссылается таблица соединения/объединения?
-
16-09-2019 - |
Вопрос
У меня есть следующие три таблицы без каскадных отношений (мне это не нужно, поскольку база данных в основном управляется NHibernate).
Invoice
(
entity_id int not null,
...
)
Ticket
(
entity_id int not null,
...
)
InvoiceTicket
(
InvoiceId --> Not-null foreign key to Invoice.entity_id
TicketId --> Not-null Foreign key to Ticket.entity_id
)
Я пытаюсь удалить счета-фактуры, билеты и связанные строки InvoiceTicket с учетом критериев в Ticket.Но мне приходится делать это вне нашего приложения, поэтому я создаю для этого SQL-запрос.
Я уже удалил все зависимости как от Invoice, так и от Ticket, без проблем.Поскольку InvoiceTicket ссылается на InvoiceTicket и Ticket, я должен сначала удалить строки InvoiceTicket.Однако если я это сделаю, то моя ссылка на таблицу счетов-фактур будет нарушена (я все равно смогу удалить интересующие билеты, но не счета-фактуры).
Какой общепринятый метод выполнения этой операции с использованием SQL?
Я уже решил проблему, используя временную таблицу и заполняя ее интересующими строками из таблицы InvoiceTicket, но что делают другие люди для решения проблемы такого типа?Я предполагаю, что вы могли бы сделать это и с помощью хранимой процедуры, но я не так хорошо знаком с их написанием.Есть ли прямой способ выполнить эту операцию с помощью SQL-запросов?
Решение
Если счета-фактуры могут существовать без связанных с ними счетов-фактур, то решение RBarryYoung — дерьмо.Он удаляет каждый такой счет.
В таком случае, чтобы правильно Чтобы определить набор счетов-фактур, подлежащих удалению, необходимо сначала запросить их и отложить в сторону.
Другие советы
Ну вот как бы я это сделал:
BEGIN TRANSACTION
DELETE FROM InvoiceTicket
WHERE EXISTS(
SELECT *
FROM TICKET t
WHERE {t.* conditions are met}
)
DELETE FROM Ticket
WHERE {t.* conditions are met}
DELETE FROM Invoice
WHERE NOT EXISTS(
SELECT *
FROM InvoiceTicket it
WHERE Invoice.entity_id = InvoiceTicket.InvoiceId
)
COMMIT TRANSACTION
Было обоснованно указано, что этот подход (выше) работает только в том случае, если для счетов-фактур требуется хотя бы один связанный билет.Хотя это правда, но возникает и обратный вопрос: действительно ли вы хотите УДАЛИТЬ каждый счет, связанный с вашими совпадающими билетами?Потому что они также могут быть связаны с другими, не удаленными заявками.
Вы можете поместить строки из InvoiceTicket во временную таблицу, а затем удалить InvoiceTicket, Ticket и, наконец, Invoice из идентификаторов во временной таблице.Наконец сдуйте временный стол.
Я не знаю, поддерживается ли это всеми СУБД, но в MySQL вы можете удалять таблицы из JOIN.Что-то вроде:
DELETE Invoice, Ticket, InvoiceTicket
FROM Invoice, InvoiceTicket, Ticket
WHERE (condition on Ticket)
AND Ticket.Id = InvoiceTicket.TicketId
AND InvoiceTicket.InvoiceId = Invoice.Id
Было обоснованно отмечено, что удаление самих счетов-фактур может вызвать проблемы, если на эти счета-фактуры ссылаются счета-фактуры, которые сами по себе не удаляются.
Хотя это правда, я хочу отметить, что нигде я не имел в виду (и нигде я не имел в виду на самом деле сказал), что набор счетов, подлежащих удалению, должен быть равный к набору счетов, идентификатор которых можно найти в любом удаляемом счете-фактуре.
Если кто-то истолковал мое сообщение именно так, я хотел бы предостеречь этих людей от опасности делать предположения слишком легко и слишком поспешно.