How can the INSERT … ON CONFLICT (id) DO UPDATE… syntax be used with a sequence ID?

房东的猫 提交于 2019-12-23 17:25:58

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!