问题
In postgresql 9.5 how can the INSERT ... ON CONFLICT (id) DO UPDATE... syntax be used with a sequence ID?
In a table tbltest
that has the following columns:
- tbltest_ID
- tbltest_Name
- tbltest_Description
Where tbltest_ID
has a sequence in the db that does auto increment.
The following works fine for updates, eg; updating the record with an ID of 4:
INSERT INTO tbltest (
tbltest_ID,
tbltest_Name,
tbltest_Description)
VALUES
(4, 'test name','test description')
ON CONFLICT (tbltest_ID) DO UPDATE SET (
tbltest_Name,
tbltest_Description) = (
excluded.tbltest_Name,
excluded.tbltest_Description) RETURNING *;
But in order to get the DB to create the sequence ID for inserts I need to remove the ID column from the statement:
INSERT INTO tbltest (
tbltest_Name,
tbltest_Description)
VALUES
('test name','test description')
ON CONFLICT (tbltest_ID) DO UPDATE SET (
tbltest_Name,
tbltest_Description) = (
excluded.tbltest_Name,
excluded.tbltest_Description) RETURNING *;
This becomes a problem if I want to update multiple records some new and some existing. As if I remove the ID column, they all be come inserts, and if I leave it in there, I have to provide an ID value in the VALUES array for each row, and when I define an ID, the sequence (db's auto increment) is no longer used.
How is the INSERT ... ON CONFLICT (id) DO UPDATE... syntax spost to be used with a sequence ID to insert/update an set of records that will contain both new records and existing records?
For example, the following does not work:
INSERT INTO tbltest (
tbltest_ID,
tbltest_Name,
tbltest_Description)
VALUES
(NULL, 'new record','new record description'),
(4, 'existing record name','existing record description')
ON CONFLICT (tbltest_ID) DO UPDATE SET (
tbltest_Name,
tbltest_Description) = (
excluded.tbltest_Name,
excluded.tbltest_Description) RETURNING *;
It throws an error:
ERROR: null value in column "tbltest_ID" violates not-null constraint
Thanks for your time.
回答1:
Ok just worked it out. I read this great article from Neil Conway: http://www.neilconway.org/docs/sequences/
Where he shows the use of the DEFAULT
keyword to tell the DB to use the sequence value for the column.
So here is the updated example that now works:
INSERT INTO tbltest (
tbltest_ID,
tbltest_Name,
tbltest_Description)
VALUES
(DEFAULT, 'new record','new record description'),
(4, 'existing record name','existing record description')
ON CONFLICT (tbltest_ID) DO UPDATE SET (
tbltest_Name,
tbltest_Description) = (
excluded.tbltest_Name,
excluded.tbltest_Description) RETURNING *;
Hope this helps someone ;-)
来源:https://stackoverflow.com/questions/39671818/how-can-the-insert-on-conflict-id-do-update-syntax-be-used-with-a-seque