这是我的简单测试
表,
create table test (
id int not null generated always as identity,
first_name. varchar,
primary key (id),
unique(first_name)
);
作为 insert-into-on-conflict
句子的替代方案,我尝试使用 coalesce
懒惰来执行 select
每当仅当 select
找不到行时才可能或 insert
。
coalesce
懒惰在文档中进行了描述。请参阅https://www.postgresql.org/docs/current/functions-conditional.html
Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; that is, arguments to the right of the first non-null argument are not evaluated. This SQL-standard function provides capabilities similar to NVL and IFNULL, which are used in some other database systems.
我还想获取该行的 id
值,无论是否插入。
我开始于:
select coalesce (
(select id from test where first_name='carlos'),
(insert into test(first_name) values('carlos') returning id)
);
但是在“into”处或附近发现了错误语法错误
。
在另一个 DBFiddle 上查看它
https://www.db-fiddle.com/f/t7TVkoLTtWU17iaTAbEhDe/0
然后我尝试了:
select coalesce (
(select id from test where first_name='carlos'),
(with r as (
insert into test(first_name) values('carlos') returning id
) select id from r
)
);
这里我收到一个 WITH 子句包含数据修改语句必须位于顶层
错误,我不明白,因为 insert
是第一个并且with
中唯一的句子。
我正在使用 DBFiddle 和 PostgreSQL 13 对此进行测试。源代码可以在以下位置找到 https://www.db-fiddle.com/f/hp8T1iQ8eS4wozDCBhBXDw/5
最佳答案
不同的方法:链式 CTE:
CREATE TABLE test
( id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY PRIMARY KEY
, first_name VARCHAR UNIQUE
);
WITH sel AS (
SELECT id FROM test WHERE first_name = 'carlos'
)
, ins AS (
INSERT INTO test(first_name)
SELECT 'carlos'
WHERE NOT EXISTS (SELECT 1 FROM test WHERE first_name = 'carlos')
RETURNING id
)
, omg AS (
SELECT id FROM sel
UNION ALL
SELECT id FROM ins
)
SELECT id
FROM omg
;
关于postgresql - PostgreSQL 中包含 insert into 子句的合并语句失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68972062/