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

Компактни или преномерирани идентификатори за всички таблици и нулиране на последователности до max(id)?

Въпросът е стар, но получихме нов въпрос от отчаян потребител на dba.SE, след като се опита да приложи това, което е предложено тук. Намерете отговор с повече подробности и обяснение там :

текущо приетият отговор ще се провали в повечето случаи .

  • Обикновено имате PRIMARY KEY или UNIQUE ограничение на id колона, която е NOT DEFERRABLE по подразбиране. (OP споменава references and constraints .) Такива ограничения се проверяват след всеки ред, така че най-вероятно ще получите уникално нарушение грешки при опит. Подробности:

  • Обикновено човек иска да запази оригиналния ред на редовете при затваряне на пропуски. Но редът, в който се актуализират редовете, е произволен , което води до произволни числа. Демонстрираният пример изглежда запазва оригиналната последователност, тъй като физическото съхранение все още съвпада с желания ред (вмъкнати редове в желания ред само миг по-рано), което почти никога не е случаят в приложенията от реалния свят и е напълно ненадеждно.

Въпросът е по-сложен, отколкото може да изглежда на пръв поглед. Едно решение (наред с други), ако можете да си позволите временно да премахнете ограничението PK / UNIQUE (и свързаните ограничения FK):

BEGIN;

LOCK tbl;

-- remove all FK constraints to the column

ALTER TABLE tbl DROP CONSTRAINT tbl_pkey;  -- remove PK

-- for the simple case without FK references - or see below:    
UPDATE tbl t  -- intermediate unique violations are ignored now
SET    id = t1.new_id
FROM  (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
WHERE  t.id = t1.id;

-- Update referencing value in FK columns at the same time (if any)

SELECT setval('tbl_id_seq', max(id)) FROM tbl;  -- reset sequence

ALTER TABLE tbl ADD CONSTRAINT tbl_pkey PRIMARY KEY(id); -- add PK back

-- add all FK constraints to the column back

COMMIT;

Това също е много по-бързо за големи таблици, тъй като проверката на PK (и FK) ограничение(я) за всеки ред струва много повече от премахването на ограничението(ята) и добавянето му(тях) обратно.

Ако има FK колони в други таблици, препращащи към tbl.id , използвайте CTE, модифициращи данни за да актуализирате всички тях.

Пример за таблица fk_tbl и FK колона fk_id :

WITH u1 AS (
   UPDATE tbl t
   SET    id = t1.new_id
   FROM  (SELECT id, row_number() OVER (ORDER BY id) AS new_id FROM tbl) t1
   WHERE  t.id = t1.id
   RETURNING t.id, t1.new_id  -- return old and new ID
   )
UPDATE fk_tbl f
SET    fk_id = u1.new_id      -- set to new ID
FROM   u1
WHERE  f.fk_id = u1.id;       -- match on old ID

Повече в референтния отговор на dba.SE .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Psql изброява всички таблици

  2. Rails 3, ActiveRecord, PostgreSQL - командата .uniq не работи?

  3. Rails Postgres - Jsonb колонна заявка

  4. Как да ПРЕДОСТАВЯ ВСИЧКИ ПРИВИЛЕГИИ на ВСИЧКИ ИЗГЛЕДИ в едно изявление?

  5. Защо да използвате IS DISTINT FROM - Postgres