DELETE linhas que não são referenciadas em outra tabela

15

Eu tenho duas tabelas em um banco de dados PostgreSQL 9.3: A tabela link_replypossui uma chave estrangeira chamada which_groupapontando para a tabela link_group.

Quero excluir todas as linhas de link_grouponde não link_replyexiste nenhuma linha relacionada . Parece bastante básico, mas eu tenho lutado com isso.

Será algo simples assim (não está funcionando)?

DELETE FROM link_group WHERE link_reply = NULL;
Hassan Baig
fonte
você tem um DDL para todo mundo olhar?
dizzystar
Dê uma olhada no operador MINUS. Você precisa especificar um campo em links_reply.
Vérace 03/04
DELETE FROM links_group USING links_group AS lg LEFT JOIN links_reply AS lr ON lg.col= lr.some_other_col WHERE links_reply.some_other_col IS NULL
213 Mihai
Eu tive uma pergunta semelhante, que também leva em consideração a simultaneidade. Consulte dba.stackexchange.com/questions/251875 .
pbillen

Respostas:

19

Citando o manual:

Há duas maneiras de excluir linhas em uma tabela usando as informações contidas em outras tabelas no banco de dados: usando sub-seleções ou especificando tabelas adicionais na USINGcláusula . Qual técnica é mais apropriada depende das circunstâncias específicas.

Negrito ênfase minha. Usar informações que não estão contidas em outra tabela é um pouco complicado, mas existem soluções fáceis. Do arsenal de técnicas-padrão à ...

... uma NOT EXISTSanti-semi-junção é provavelmente mais simples e mais eficiente para DELETE:

DELETE FROM link_group lg
WHERE  NOT EXISTS (
   SELECT FROM link_reply lr
   WHERE  lr.which_group = lg.link_group_id
   );

Assumindo (como as definições da tabela não são fornecidas) link_group_idcomo o nome da coluna da chave primária de link_group.

A técnica que @Mihai comentou também funciona (aplicada corretamente):

DELETE FROM link_group lg
USING  link_group      lg1
LEFT   JOIN link_reply lr ON lr.which_group = lg1.link_group_id
WHERE  lg1.link_group_id = lg.link_group_id
AND    lr.which_group IS NULL;

Mas como a expressão da tabela na USINGcláusula é associada à tabela de destino ( lgno exemplo) com a CROSS JOIN, você precisa de outra instância da mesma tabela que trampolim ( lg1no exemplo) para o LEFT JOIN, que é menos elegante e geralmente mais lento.

Erwin Brandstetter
fonte