вторник, 18 октября 2016 г.

Django & PostgreSQL & ERROR: duplicate key violates unique constraint

Часто при использовании PostgreSQL после перетаскивании БД с одного сервера на другой (или с локальной dev машины на production) начинают сыпаться primary keys, выдавая при insert операциях что-то вроде:

ERROR: duplicate key violates unique constraint

Дело в том, что, если, например, MySQL использует для первичных ключей autoincrement поля, которые просто увеличиваются на 1 при добавлении в таблицу каждой новой строки, то PostgreSQL использует для первичных ключей поля типа serial, которые фактически являются просто цифровыми полями, значения которых берутся из PostgreSQL последовательности (sequence). При этом если следующее значение последовательности равно 100, а id=100 в таблице уже есть, то и возникает конфликт duplicate key:

SELECT MAX(the_primary_key) FROM the_table;
SELECT nextval('the_primary_key_sequence');

Если эти первое значение больше второго или равно ему - есть проблема. Чтобы исправить ситуацию, можно установить значения всех последовательностей на заведомо большое число (которое больше всех текущих id на порядок, например), но это некрасиво и неудобно, быстрее попросить Django помочь нам. Такая короткая стандартная Django команда выведет весь SQL, который скорректирует проблему, установив корректные значения для PostgreSQL последовательностей:

./manage.py sqlsequencereset app1 app2

app1, app2 здесь - это названия Django приложений. Полученный SQL код можно просто выполнить в БД и всё - вот так просто. Django рулит!