PostgreSQL LinuxWindowsmacOS

PostgreSQL: duplicate key value violates unique constraint

  • Обновлено
  • Чтение ≈ 4 минуты

Краткий ответ

Вставка нарушает уникальный индекс. Проверьте существующие значения, используйте ON CONFLICT или исправьте последовательность (sequence).

В этой статье
  1. Что означает ошибка
  2. Причины и решения
  3. Пошаговое решение
  4. Диагностика
  5. Починка последовательности
  6. Настоящие дубли

#Что означает ошибка

Сообщение
duplicate key value

ERROR: duplicate key value violates unique constraint "table_pkey" с подробностью Key (id)=(5) already exists означает вставку значения, которое уже есть в уникальном или первичном ключе. Часто виновата рассогласованная последовательность (sequence) после импорта данных с явными id.

Определите, настоящий ли это дубль или сбой последовательности.

Лечится по-разному.

Вставка нарушает уникальный индекс. Проверьте существующие значения, используйте ON CONFLICT или исправьте последовательность (sequence).

#Причины и решения

Возможная причинаКак узнатьЧто делать
Дубликат значенияДанные.DETAIL показывает уже существующее значение столбца email или составного ключаНайдите источник повторной записи, определите, нужно ли пропустить или обновить.
Сбитая sequenceСчётчик.Повторяется конфликт автоматически назначенного id после импортаСравните MAX(id) и связанный sequence; изменять sequence только в окно обслуживания.
Гонка запросовПараллель.Два запроса пытаются вставить одинаковый логический ключ одновременноИспользуйте UNIQUE и обработку конфликта на уровне транзакции.
Импорт данныхРучные id.После импорта с явными id счётчик мог не обновитьсяПроверьте привязанный sequence и согласуйте коррекцию после резервной копии.

#Пошаговое решение

  1. Прочитайте Key и constraint в сообщенииОткройте консоль psql (например, на Linux через sudo -u postgres psql -d ИМЯ_БАЗЫ, если это соответствует вашей системе). Полностью скопируйте текст duplicate key value violates unique constraint "...", особенно строку DETAIL: Key (email)=(...) already exists. Название ограничения может относиться к первичному ключу, отдельному UNIQUE-индексу или составному ключу. До любых изменений узнайте, какая команда INSERT/UPDATE вызвала ошибку и какая таблица участвовала. Дубликат данных — обычный сценарий, не свидетельство повреждения последовательности.
  2. Найдите конфликтующую строкуЕсли в DETAIL указан реальный столбец, проверьте дубликат запросом только на чтение в SQL-редакторе вашей базы, например SELECT id, email FROM public.users WHERE email = 'example@example.com';; замените таблицу, столбец и значение на свои и избегайте раскрытия личных данных. Для составного ограничения включите все указанные поля; запрос может не обнаружить строку, если она вставлена другой транзакцией и ещё не видна. Найдите в коде, почему вставка выполняется повторно: повторный запрос, конкурентная запись, неверный ключ или повторный импорт.
  3. Сравните MAX(id) и sequenceЛишь если ошибка относится к автоматически назначаемому числовому id (SERIAL/IDENTITY), сравните максимальный идентификатор с последовательностью. В psql выполните SELECT pg_get_serial_sequence('public.users','id'); и SELECT max(id) FROM public.users;, предварительно заменив имена. Если первый запрос возвращает NULL, столбец не имеет связанной последовательности и этот способ не подходит. Не вызывайте nextval ради диагностики: он изменяет состояние последовательности. Столбец last_value виден только при разрешённом доступе к найденной последовательности.
  4. Выровняйте последовательностьМенять последовательность может только администратор при подтверждённом рассогласовании после импорта, на согласованном окне обслуживания и с резервной копией. При параллельных вставках setval может состязаться с приложением и создать новые дубликаты: сначала обеспечьте отсутствие конкурирующих записей. Для таблицы с непустыми положительными идентификаторами пример — SELECT setval(pg_get_serial_sequence('public.users','id'), (SELECT max(id) FROM public.users), true);; при пустой таблице и иных шагах/минимумах алгоритм будет другим. Проверьте фактическое следующее значение на тестовой вставке, не изменяя производственные записи без согласования.
  5. Используйте ON CONFLICT для настоящих дублейЕсли конфликт возник при повторном создании одной и той же записи, определите бизнес-правило. INSERT ... ON CONFLICT (email) DO NOTHING уместен, только когда повтор можно пропустить, а DO UPDATE SET ... — когда действительно нужно обновить существующую запись. Вставьте конструкцию в код приложения и проверьте её в транзакции на тестовой базе: убедитесь, что другое уникальное ограничение не нарушается. Не используйте ON CONFLICT для маскировки ошибочно повторяющегося запроса или перезаписи важных полей.

#Диагностика

Прочитайте строку DETAIL из исключения и определите, какие значения вызвали конфликт. Для email это обычно реальный дубликат, а для автоматически выдаваемого числового id может быть ошибочный счётчик последовательности. SELECT MAX(id) и pg_get_serial_sequence(...) применяйте только к точной таблице и при подтверждённом сценарии.

#Починка последовательности

Рассогласование sequence исправляет администратор только после резервной копии, проверки реального диапазона идентификаторов и исключения параллельных вставок. setval меняет состояние последовательности и может породить новый конфликт, если выполнить его вслепую. Пустые таблицы, пользовательские начальные значения и шаги последовательности требуют отдельного алгоритма.

#Настоящие дубли

Для ожидаемых повторов можно выбрать ON CONFLICT ... DO NOTHING или контролируемое DO UPDATE, но только в соответствии с правилами приложения и на тестовой базе. Перед созданием UNIQUE-индекса проверьте дубли; автоматическое удаление строк без анализа ссылок и внешних ключей недопустимо.

SQLКоманда
Только диагностические запросы: подставьте фактическое имя таблицы и столбца. Команда setval вынесена в условный шаг; без подтверждённой причины не запускать.
SELECT pg_get_serial_sequence('public.users','id');
SELECT MAX(id) FROM public.users;

Так эту ошибку тоже называют

Источники и обновления

Последнее обновление статьи: 1 ноября 2026. Версии программ и интерфейсы меняются — если шаги не совпадают с вашей версией, сверяйтесь с документацией производителя.