Каков общепринятый метод удаления записей, на которые ссылается таблица соединения/объединения?

StackOverflow https://stackoverflow.com/questions/1477689

  •  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

Было обоснованно отмечено, что удаление самих счетов-фактур может вызвать проблемы, если на эти счета-фактуры ссылаются счета-фактуры, которые сами по себе не удаляются.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top