Qual é o método aceito para excluir registros referenciados por uma junção / associar-se mesa?

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

  •  16-09-2019
  •  | 
  •  

Pergunta

Eu tenho três tabelas a seguir, com NO cascata relacionamentos (Eu não quero isso, como o banco de dados é gerido principalmente por 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
)

O que eu estou tentando fazer é excluir as faturas, bilhetes, e linhas InvoiceTicket relacionados dado um critério no bilhete. Mas eu tenho que fazer isso externamente para a nossa aplicação, daí porque eu estou construindo uma consulta SQL para fazê-lo.

Eu já excluiu todas as dependências para ambos fatura e Ticket, não há problema. Desde Invoice e Ticket são referenciados por InvoiceTicket, devo excluir linhas InvoiceTicket primeiro. No entanto, se eu fizer isso, então meu link para a tabela Invoice é quebrado (eu ainda pode excluir os bilhetes de interesse, mas não as facturas).

O que é o método aceito para executar esta operação usando SQL?

Eu resolvi o problema já usando uma tabela temporária e preenchê-lo com as linhas de interesse da tabela InvoiceTicket, mas o que as outras pessoas fazendo para resolver este tipo de problema? Eu imagino que você poderia fazer isso com um procedimento armazenado, bem como, mas eu não sou tão familiarizado com a escrita aqueles. Existe uma maneira direta de se fazer esta operação através de consultas SQL?

Foi útil?

Solução

Se faturas podem validamente existir sem invoicetickets associados, em seguida, a solução da RBarryYoung é uma porcaria. Apaga cada essa factura.

Nesse caso, a fim de corretamente determinar o conjunto de facturas para apagar, primeiro você deve consultá-los e retirá-las.

Outras dicas

Bem, aqui está como eu faria isso:

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

Tem sido validamente apontou que esta abordagem (acima) só funciona se Facturas exigem pelo menos um bilhete associada. Embora isto seja verdade, ele também levanta a questão inverso, o que é que você realmente deseja excluir todos os factura associada com os seus bilhetes de harmonização? Porque eles também podem estar associados a outros bilhetes-deletados não, bem.

Você poderia colocar as linhas de InvoiceTicket em uma tabela temporária, em seguida, InvoiceTicket de exclusão, Ticket e, finalmente factura do ids da tabela temporária. Finalmente soprar a tabela temporária.

Eu não sei se isso é suportado por todos os DBMS, mas no MySQL, você pode excluir um JOIN nas mesas. Algo como:

DELETE Invoice, Ticket, InvoiceTicket
FROM Invoice, InvoiceTicket, Ticket
WHERE (condition on Ticket) 
  AND Ticket.Id = InvoiceTicket.TicketId 
  AND InvoiceTicket.InvoiceId = Invoice.Id

Tem sido validamente apontou que a exclusão do faturas si pode dar origem a problemas se essas facturas são referenciados por invoicetickets que são eles próprios não excluída.

Enquanto verdade, eu quero salientar que em nenhum lugar tenho a intenção de sugerir (e em nenhum lugar tem I realmente disse ) que o conjunto de facturas-a-ser-excluídos deve ser igual para o conjunto de facturas cujo id pode ser encontrado em qualquer invoiceticket-a-ser-excluídos.

Se alguém interpretou a minha mensagem para dizer isso, eu gostaria de alertar as pessoas contra os perigos de fazer suposições muito facilmente e muito ansioso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top