Как LIMIT взаимодействует с DELETE по первичному ключу в Postgres? (Исправить поврежденный уникальный индекс)

Мне передали базу данных, которая застряла в странном состоянии. В какой-то неопределенное время в прошлом я оказался в ситуации, когда у меня были повторяющиеся строки в одной таблице с одним и тем же первичным ключом:

=> \d my_table
Table "public.my_table"
       Column       |          Type           | Modifiers 
--------------------+-------------------------+-----------
 id                 | bigint                  | not null
 some_data          | bigint                  | 
 a_string           | character varying(1024) | not null
Indexes:
"my_table_pkey" PRIMARY KEY, btree (id)

=> SELECT id, count(*) FROM my_table GROUP BY id HAVING count(*) > 1 ORDER BY id;
#50-some results, non-consecutive rows.

Я понятия не имею, как база данных попала в такое состояние, но я хочу иметь возможность безопасно выйти из него. Если для каждого дублированного первичного ключа выполнить запрос вида:

DELETE FROM my_table WHERE id = "a_duplicated_row" LIMIT 1;

Будет ли удалена только одна строка из таблицы или будут удалены обе строки с заданным первичным ключом?


person Andrew Rueckert    schedule 03.04.2014    source источник
comment
Насколько я знаю, введенный вами SQL недействителен - На справочной странице Postgres для операторов DELETE не упоминается предложение LIMIT. Таким образом, ответ на непосредственный вопрос — ни то, ни другое, это ошибка. Ответ на неявный вопрос, как удалить одну строку из пары дубликатов, можно найти в другом месте.   -  person IMSoP    schedule 03.04.2014
comment
Название вопроса должно быть больше похоже на «Как исправить поврежденный уникальный индекс».   -  person Daniel Vérité    schedule 03.04.2014


Ответы (1)


Увы, PostgreSQL еще не реализует LIMIT для DELETE или UPDATE. Если строки неразличимы во всех остальных отношениях, вам нужно будет осторожно использовать скрытый столбец ctid, чтобы разорвать связи, как обсуждалось здесь. Или просто создайте таблицу, выбрав отдельные кортежи из существующей таблицы и переименовав их.

person jjanes    schedule 03.04.2014
comment
@AndrewRueckert Также прочитайте wiki.postgresql.org/wiki/Corruption . Прежде чем делать что-либо еще, вы должны сделать резервную копию — предпочтительно как копию на уровне файловой системы (pg_basebackup), так и логический дамп с pg_dump. После того, как вы устранили конфликт, вы должны переиндексировать его, а затем начать серьезное расследование возможной причины. - person Craig Ringer; 04.04.2014