sql >> Database teknologi >  >> RDS >> PostgreSQL

Kompakte eller omnummerere ID'er for alle tabeller, og nulstille sekvenser til max(id)?

Spørgsmålet er gammelt, men vi fik et nyt spørgsmål fra en desperat bruger på dba.SE efter at have forsøgt at anvende det, der foreslås her. Find et svar med flere detaljer og forklaring derovre :

Det aktuelt accepterede svar vil mislykkes i de fleste tilfælde .

  • Typisk har du en PRIMARY KEY eller UNIQUE begrænsning på et id kolonne, som er NOT DEFERRABLE som standard. (OP nævner references and constraints .) Sådanne begrænsninger kontrolleres efter hver række, så du højst sandsynligt får unik overtrædelse fejl ved at prøve. Detaljer:

  • Typisk ønsker man at beholde den oprindelige rækkefølge mens der lukkes huller. Men rækkefølgen, som rækker opdateres i, er vilkårlig , hvilket fører til vilkårlige tal. Det viste eksempel ser ud til at bibeholde den oprindelige rækkefølge, fordi fysisk lagring stadig falder sammen med den ønskede rækkefølge (indsatte rækker i ønsket rækkefølge blot et øjeblik tidligere), hvilket næsten aldrig er tilfældet i applikationer fra den virkelige verden og fuldstændig upålidelig.

Sagen er mere kompliceret, end den umiddelbart kan se ud. En løsning (blandt andre), hvis du har råd til midlertidigt at fjerne PK / UNIQUE-begrænsningen (og relaterede FK-begrænsninger):

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;

Dette er også meget hurtigere for store borde, fordi kontrol af PK (og FK) begrænsning(er) for hver række koster meget mere end at fjerne begrænsning(erne) og tilføje dem igen.

Hvis der er FK-kolonner i andre tabeller, der refererer til tbl.id , brug datamodificerende CTE'er for at opdatere dem alle.

Eksempel på en tabel fk_tbl og en FK-kolonne 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

Mere i referencede svar på dba.SE .



  1. Indsæt i databaseproblem... (Dårlig tegnkodning) PHP/MYSQL

  2. MySQL-ækvivalent til Oracles SEQUENCE.NEXTVAL

  3. Oracle sql:rækkefølge efter og distinkt klausul

  4. java-kode til import af xls-data til mysql-databasen