BORRAR filas que no están referenciadas en otra tabla

15

Tengo dos tablas en una base de datos PostgreSQL 9.3: la tabla link_replytiene una clave foránea llamada which_groupapuntando a la tabla link_group.

Quiero eliminar todas las filas de link_groupdonde no link_replyexiste una fila relacionada . Suena bastante básico pero he estado luchando con eso.

¿Será algo simple como esto (no funciona)?

DELETE FROM link_group WHERE link_reply = NULL;
Hassan Baig
fuente
¿Tienes un DDL para que todos lo vean?
dizzystar
Echa un vistazo al operador MINUS. Debe especificar un campo en links_reply.
Vérace
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
Mihai
Tuve una pregunta similar, que también tiene en cuenta la concurrencia. Consulte dba.stackexchange.com/questions/251875 .
pbillen

Respuestas:

19

Citando el manual:

Hay dos formas de eliminar filas en una tabla usando la información contenida en otras tablas de la base de datos: usando sub-selecciones o especificando tablas adicionales en la USINGcláusula . La técnica más apropiada depende de las circunstancias específicas.

El énfasis audaz es mío. Usar información que no está contenida en otra tabla es un poco complicado, pero hay soluciones fáciles. Desde el arsenal de técnicas estándar hasta ...

... un NOT EXISTSanti-semi-join es probablemente el más simple y más eficiente para DELETE:

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

Asumiendo (dado que no se proporcionan definiciones de tabla) link_group_idcomo nombre de columna para la clave primaria de link_group.

La técnica que comentó @Mihai también funciona (aplicada correctamente):

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;

Pero dado que la expresión de tabla en la USINGcláusula se une a la tabla de destino ( lgen el ejemplo) con a CROSS JOIN, necesita otra instancia de la misma tabla que el trampolín ( lg1en el ejemplo) para el LEFT JOIN, que es menos elegante y generalmente más lento.

Erwin Brandstetter
fuente