sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo eliminar filas duplicadas con dependencias de claves externas?

Puede hacer esto de manera mucho más eficiente con una instrucción SQL única con CTE de modificación de datos .

WITH plan AS (
   SELECT *
   FROM  (
      SELECT recid, min(recid) OVER (PARTITION BY cdesc) AS master_recid
      FROM   cpt
      ) sub
   WHERE  recid <> master_recid  -- ... <> self
   )
 , upd_lab AS (
   UPDATE lab l
   SET    cpt_recid = p.master_recid   -- link to master recid ...
   FROM   plan p
   WHERE  l.cpt_recid = p.recid
   )
DELETE FROM cpt c
USING  plan p
WHERE  c.recid = p.recid
RETURNING c.recid;

db<>fiddle aquí (pág. 11)
SQL Fiddle (pág. 9.6)

Esto debería ser mucho más rápido y más limpio. Los bucles son comparativamente caros, el manejo de excepciones es comparativamente aún más caro.
Más importante aún, las referencias en lab se redirigen a la fila principal respectiva en cpt automáticamente, que aún no estaba en su código original. Para que pueda eliminar todos los duplicados a la vez .

Todavía puede envolver esto en una función plpgsql o SQL si lo desea.

Explicación

  1. En el 1er CTE plan , identifique una fila maestra en cada partición con el mismo cdesc . En su caso, la fila con el mínimo recid .

  2. En el 2º CTE upd_lab redirigir todas las filas que hacen referencia a un duplicado a la fila principal en cpt .

  3. Finalmente, elimine duplicados, lo que no generará excepciones porque las filas dependientes se vinculan a la fila maestra restante prácticamente al mismo tiempo.

ON DELETE RESTRICT

Todas las CTE y la consulta principal de una sentencia operar en la misma instantánea de tablas subyacentes, virtualmente simultáneamente . No ven los efectos de los demás en las tablas subyacentes:

Uno podría esperar una restricción FK con ON DELETE RESTRICT generar excepciones porque, [según la documentación][3]:

Sin embargo, la declaración anterior es un comando único y, [el manual otra vez][3]:

Énfasis en negrita mío. Funciona para el valor predeterminado menos restrictivo ON DELETE NO ACTION también, por supuesto.

Pero tenga cuidado con las transacciones simultáneas que se escriben en las mismas tablas, pero esa es una consideración general, no específica de esta tarea.

Se aplica una excepción para UNIQUE y PRIMARY KEY restricción, pero eso no concierne a esto caso: