sequelize: Running sequelize:seed for Postgres with autoIncrement key breaks SERIAL data type in tables
What are you doing?
I’m trying to use migrations to create tables with autoIncrement key in Postgres
It is said here
http://docs.sequelizejs.com/manual/advanced/legacy.html
that adding autoIncrement: true
// Automatically gets converted to SERIAL for postgres
// my migration
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Books', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
...
// my model
let Book = sequelize.define(
'Book', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
...
// run command
sequelize:migrate
// on server I run
Book.create({title: 'title', author: 'author'});
What do you expect to happen?
I expect that new book is added to database
What is actually happening?
But I see an error:
duplicate key value violates unique constraint \"Books_pkey\""
However without sequelize migrations database works without problems.
CREATE TABLE "Books" (
id SERIAL PRIMARY KEY,
title VARCHAR(100) NOT NULL,
author VARCHAR(100) NULL
);
--I can insert without problems
INSERT INTO "Books" (id, title, author) VALUES (DEFAULT, 'title', 'author');
INSERT INTO "Books" (id, title, author) VALUES (DEFAULT, 'title', 'author');
Dialect: postgres Dialect version: 10.3.0 Database version: 10.3.0 Sequelize version: 4.37.5 Tested with latest release: Yes
Note : Your issue may be ignored OR closed by maintainers if it’s not tested against latest version OR does not follow issue template.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 2
- Comments: 23 (3 by maintainers)
You do NOT need to add the
id
attribute to your model definition.Do it like this:
The documentation you are reading is intended only for tables that use a column name other than
id
for your primary key, likebooks_id
, or something.@mickhansen
I found a better solution since last visiting this issue. At least in my case, the
id
values don’t necessarily correlate with how many records there are (eg, deletions).Assuming you know the sequence name, you can just do this:
If you had 100 records, for example, but your largest
users.id
value is126
then relying onUsers.count()
alone will set you up for conflict, since101
(the next ID) probably/can already exist.You can verify what the next
id
value will be with this:I ended up doing something similar to what @lukeed did. A new seed with this code:
For anyone that stumbles onto this 😄
Addition: it stops working after using
sequelize:seed
to insert several lines to table. Is any way to sync somehow sequelize models with latest id in table?So the indexing is incorrect on the database side (too?). I’m really not familiar with Sequelize code, so not sure if it’s relying on the DB index only or if it had its own.
Temporary workaround (to fix the DB sequence) is to run an
ALTER
sequence after the appropriate seeder has run:Thanks a lot, thanks to the ideas above I solved this problem. As a result, I got the following:
Model:
Seed File:
Confirmed. Running any seeding operation with
id
values included in the seed data will break Sequelize.I’ve tried with
items.map(o => User.create(o)
,User.bulkCreate(items)
,... { individualHooks:true }
andQ.bulkInsert('users', items)
. The data is entered fine, but Sequelize totally “loses track” of how many items there are in the database, so any new inserts or updates will throw the error @Darmikon mentioned.Worth noting that the
id
Sequelize wants to use is always wrong. It also varies. It can be(id=1)
or(id=89)
… no rhythm to the number it tries to use.For anyone who stumbles across this, my mistake was
defaultValue: uuid()
instead ofdefaultValue: uuid
.defaultValue
was being set to a static value rather than generating a new uuid each time a record was created.I got past this issue by setting
id
attribute to <Model>.max(‘id’) + 1 during creation of model instance after seeding. This is also one of the solutions suggested by the article shared by @sushantdhimanPostgres serial needs to be reset if you want to supply your own ids. This error appears when serial counter is ahead than the id you are trying to insert.
https://dba.stackexchange.com/questions/60802/fixing-table-structure-to-avoid-error-duplicate-key-value-violates-unique-cons
In my case I was forced to use UUID instead of INTEGER. So no more autoIncrement and INTEGER for my id fields