sql >> Database >  >> RDS >> PostgreSQL

Dubbele rijen in een primaire sleuteltabel.

Weer terug, minder tijd om te bloggen 🙂

"FOUT:kan geen unieke index maken
DETAIL:tabel bevat dubbele waarden."

Deze fout wordt weggegooid door Postgres wanneer het dubbele rijen tegenkomt in een primaire-sleuteltabel door een van deze opdrachten REINDEX of CREATE UNIQUE INDEX te laten mislukken.

Waarom staan ​​er dubbele rijen in een tabel?

Ik weet het niet precies 🙂 noch enige bewezen uitleg...
Twee dingen in mijn gedachten.

Ten eerste kan het een vertraagde indexcreatie zijn of als u gedeelde sequenties in een database hebt, kan het delen op twee verschillende primaire sleuteltabellen de oorzaak zijn bij het herstellen van de gegevens in de tabel (pg_restore). Ten tweede, als er een enorme transactie plaatsvindt op die tafel en aan de backend heeft iemand de instantie abrupt gestopt, wat ook kan gebeuren dat de index (primaire sleutel) niet naar de juiste rij wijst.

Hoe op te lossen?

Welnu, zoals gebruikelijk, wanneer we dubbele rijen in een tabel tegenkomen (ondanks welke reden dan ook), filteren we eerst de dubbele rijen en verwijderen ze, en later zou REINDEX het probleem moeten oplossen.

Query voor het vinden van dubbele rijen:

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

Zelfs nadat het verwijderen van de dubbele rijen REINDEX of CREATE UNIQUE INDEX mislukt, betekent dit dat uw index niet goed is opgeschoond. Bovenstaande query geeft mogelijk geen 100% resultaatgerichte uitvoer wat u verwacht, omdat de query de index gaat kiezen die al is beschadigd met dubbele rijen. Zie hieronder het uitlegplan.

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)

We moeten CTID van dubbele rijen uit de hoofdtabel halen en verwijderen met voorwaardelijke instructie als CTID + PRIMARY KEY VALUE.

Ik heb een beetje met pg_catalogs gespeeld om de Primary Key Table te annuleren om het scenario met een vergelijkbare fout te reproduceren. (Alsjeblieft niet)

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

Mijn tabeldefinitie en gegevens:

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)

Laten we dit nu oplossen...

Stap 1. Maak een nieuwe tabel van de betreffende tabel door slechts twee kolomwaarden CTID en PRIMARY KEY op te halen.

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

Stap 2. Laten we nu de dubbele vinderquery uitvoeren met CTID om de exacte duplicaten te krijgen.

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)

Stap 3. Op het bovenstaande resultaat kunt u nu één rij uit de hoofdtabel (bewerkte tabel) verwijderen met CTID.

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

Stap 4. Nu zal uw REINDEX of CREATE UNIQUE INDEX succesvol zijn.

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)

Stap 5. Vergeet niet om onmiddellijk VACUM ANALYSE op de tafel uit te voeren om de systeemcatalogi en de CTID-beweging bij te werken.

Deel alstublieft uw opmerkingen.


  1. PL/SQL Strong-referentiecursor met door de gebruiker gedefinieerd recordgegevenstype

  2. Dubbele records zoeken in MySQL

  3. Django oracle db-instellingen

  4. Hoe het numerieke deel van een string te krijgen met behulp van T-SQL?