Sql Upsert/on与串行主键冲突
upsert使用onconflict工作,但id的数据类型是serial,这意味着我希望它自动生成/递增。如果我在不指定id的情况下进行插入,则插入工作正常 我的问题是将两者结合起来。要使密钥自动递增,我不会将id传递到insert中,但如果我不传递id,则更新将永远不会触发。我不能将null传递给id,因为它是非null字段 在下面的示例中-我第一次运行查询,它确实插入,第二次它确实更新,但我不知道如何传递“nothing”以插入,因此标识键仍然可以在插入时工作。我可以在insert中设置默认值,但是如果有实际的id值,我就不能传递它Sql Upsert/on与串行主键冲突,sql,postgresql,Sql,Postgresql,upsert使用onconflict工作,但id的数据类型是serial,这意味着我希望它自动生成/递增。如果我在不指定id的情况下进行插入,则插入工作正常 我的问题是将两者结合起来。要使密钥自动递增,我不会将id传递到insert中,但如果我不传递id,则更新将永远不会触发。我不能将null传递给id,因为它是非null字段 在下面的示例中-我第一次运行查询,它确实插入,第二次它确实更新,但我不知道如何传递“nothing”以插入,因此标识键仍然可以在插入时工作。我可以在insert中设置默认
CREATE TABLE public.upsert_test
(
id INTEGER NOT NULL DEFAULT nextval('upsert_test_id_seq'::regclass),
name character varying(20) COLLATE pg_catalog."default",
description character varying(20) COLLATE pg_catalog."default",
CONSTRAINT upsert_test_pkey PRIMARY KEY (id)
)
INSERT INTO upsert_test (id, name, description)
VALUES (1, 'thing1', 'test')
on conflict (id)
do update set (name , description) = ('thing_updated','test-updated')
where upsert_test.id = 1;
您可以将查询更改为使用序列函数,如:
INSERT INTO upsert_test (id, name, description)
VALUES ((select nextval('upsert_test_id_seq')), 'thing1', 'test')
on conflict (id)
do update set (name , description) = ('thing_updated','test-updated')
where upsert_test.id = (select currval('upsert_test_id_seq'));
注意,这可能不是线程安全的,例如,如果在第一次调用中select currval('upsert\u test\u id\u seq')
之前执行对此sql的第二次调用,则在第一次查询中更新可能失败
在op提供更多信息后更新
您可以将查询更改为如下所示:
INSERT INTO upsert_test (id, name, description)
VALUES (COALESCE(:YOUR_ID_PARAM, (select nextval('upsert_test_id_seq'))), 'thing1', 'test')
on conflict (id)
do update set (name , description) = ('thing_updated','test-updated')
where upsert_test.id = :YOUR_ID_PARAM;
注意,我添加了这个函数,所以如果您的参数为null,那么使用sequence nextval。此外,更新现在还使用您的参数。谢谢您的回复。我想我需要在提交到查询之前测试'id'变量,如果它为null,那么我会按照您的建议将其更改为nextval函数。我希望不必操纵id值,但这似乎会奏效。谢谢,我不清楚你想要空支票,我更新了答案。是的,效果很好。我尝试了值(COALESCE(:YOUR_ID_PARAM,(Default)),'thing1','test'),但在这个上下文中它似乎不喜欢默认值。谢谢