PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Как да премахнете дублиращи се редове със зависимости от външни ключове?

Можете да направите това много по-ефективно с един SQL оператор с CTE, модифициращи данни .

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 тук (стр. 11)
SQL Fiddle (стр. 9.6)

Това трябва да емного по-бързо и по-чисто. Цикълът е сравнително скъп, обработката на изключения е сравнително още по-скъпа.
По-важното е, че препратките в lab се пренасочват към съответния главен ред в cpt автоматично, което все още не е във вашия оригинален код. Така че можете да изтриете всички дублирания наведнъж .

Все още можете да обвиете това в plpgsql или SQL функция, ако желаете.

Обяснение

  1. В 1-ви CTE plan , идентифицирайте главен ред във всеки дял със същия cdesc . Във вашия случай редът с минималния recid .

  2. Във 2-ри CTE upd_lab пренасочва всички редове, препращащи към дублиране, към главния ред в cpt .

  3. И накрая, изтрийте дупки, което няма да доведе до изключения, тъй като зависещите редове се свързват с оставащия главен ред почти по същото време.

ON DELETE RESTRICT

Всички CTE и основната заявка на изявление работят върху една и съща моментна снимка на базови таблици, практически едновременно . Те не виждат ефектите на другия върху основните таблици:

Може да се очаква FK ограничение с ON DELETE RESTRICT да предизвика изключения, защото [по документация][3]:

Горният израз обаче е една команда и [отново ръководството][3]:

Удебелен акцент мой. Работи за по-малко рестриктивното по подразбиране ON DELETE NO ACTION също, разбира се.

Но внимавайте с едновременни транзакции, записващи в едни и същи таблици, но това е общо съображение, а не специфично за тази задача.

Важи изключение за UNIQUE и PRIMARY KEY ограничение, но това не засяга това case:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да променя стойността на единично свойство в типа данни PostgreSQL JSONB?

  2. Как да създадете уникален индекс с условна и подзаявка в PostgreSQL?

  3. Как да намерите дъщерни таблици, които наследяват от друга таблица в PSQL

  4. Определяне дали транзакцията е активна (Postgres)

  5. Избиране на съответстващо подмножество в отношение много към много