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

Righe duplicate in una tabella della chiave primaria.

Di nuovo, ottenendo molto meno tempo per il blog 🙂

"ERRORE:impossibile creare un indice univoco
DETTAGLIO:la tabella contiene valori duplicati."

Questo errore viene eliminato da Postgres quando incontra righe duplicate in una tabella di chiavi primarie fallendo uno di questi comandi REINDEX o CREATE UNIQUE INDEX.

Perché in una tabella esistono righe duplicate?

Non sono sicuro esattamente 🙂 né alcuna spiegazione provata fuori...
Due cose a mio avviso.

In primo luogo, potrebbe essere la creazione ritardata dell'indice o se hai condiviso sequenze in un database, la condivisione su due diverse tabelle di chiavi primarie potrebbe essere la causa durante il ripristino dei dati nella tabella (pg_restore). In secondo luogo, se su quel tavolo è in corso una transazione di grandi dimensioni e nel back-end qualcuno ha interrotto bruscamente l'istanza, il che potrebbe anche non riuscire a indicare la riga destra dell'indice (chiave primaria).

Come risolverlo?

Ebbene, come prassi comune, quando incontriamo righe duplicate in una tabella (a prescindere da qualsiasi motivo), prima filtriamo le righe duplicate e le eliminiamo, quindi, facendo REINDEX, dovremmo risolvere il problema.

Query per trovare righe duplicate:

select count(*),primary_column from table_name group by primary_column having count(*) > 1;

Anche dopo aver eliminato le righe duplicate REINDEX o CREATE UNIQUE INDEX non riesce, significa che l'indice non è stato pulito correttamente. La query precedente potrebbe non fornire un output orientato ai risultati al 100% ciò che ti aspetti, perché la query sceglierà l'indice che è già danneggiato con righe duplicate. Vedi il piano esplicativo di seguito.

postgres=# explain select count(*),id from duplicate_test group by id having count(*) > 1;
QUERY PLAN
-------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..5042.90 rows=99904 width=4)
Filter: (count(*) > 1)
-> Index Scan using duplicate_test_pkey on duplicate_test (cost=0.00..3044.82 rows=99904 width=4)
(3 rows)

Dobbiamo catturare CTID di righe duplicate dalla tabella principale ed eliminare con un'istruzione condizionale come CTID + VALORE CHIAVE PRIMARIA.

Ho giocato un po' con pg_catalogs per annullare la tabella delle chiavi primarie per riprodurre lo scenario con un errore simile. (Per favore, non farlo)

postgres=# create unique index idup on duplicate_test(id);
ERROR: could not create unique index "idup"
DETAIL: Key (id)=(10) is duplicated.

Definizione e dati della mia tabella:

postgres=# d duplicate_test
Table "public.duplicate_test"
Column | Type | Modifiers
--------+---------+-----------
id | integer | not null
name | text |
Indexes:
"duplicate_test_pkey" PRIMARY KEY, btree (id)

postgres=# select * from duplicate_test ;
id | name
----+---------
10 | Raghav ---Duplicate
20 | John H
30 | Micheal
10 | Raghav ---Duplicate
(4 rows)

Ora, risolviamo questo problema...

Passaggio 1. Crea una nuova tabella dalla tabella effettuata estraendo solo due valori di colonna CTID e PRIMARY KEY.

postgres=# CREATE TABLE dupfinder AS SELECT ctid AS tid, id FROM duplicate_test;
SELECT 4

Passaggio 2. Ora, eseguiamo la query di ricerca duplicati con CTID per ottenere i duplicati esatti.

postgres=# select * from dupfinder x where exists (select 1 from dupfinder y where x.id = y.id and x.tid != y.tid);
tid | id
-------+----
(0,1) | 10
(0,5) | 10
(2 rows)

Passaggio 3. Sul risultato sopra, ora puoi eliminare una riga dalla tabella principale (tabella effettuata) con CTID.

postgres=# delete from duplicate_test where ctid='(0,5)' and id=10;
DELETE 1

Passaggio 4. Ora, il tuo REINDEX o CREATE UNIQUE INDEX avrà successo.

postgres=# create unique index idup on duplicate_test(id);
CREATE INDEX

postgres=# select * from duplicate_test ;
id | name
----+---------
10 | Raghav
20 | John H
30 | Micheal
(3 rows)

Passaggio 5. Non dimenticare di eseguire immediatamente l'ANALISI DEL VUOTO sul tavolo per aggiornare i cataloghi del sistema e il movimento CTID.

Per favore condividi i tuoi commenti.