我有一个postgres数据库架构,其中新插入的行引用其他行。表格的骨架是:
CREATE TABLE table_1 (
f1 UUID PRIMARY KEY,
f2 UUID NOT NULL,
f3 text NOT NULL,
f4 text NOT NULL DEFAULT '',
f5 text NOT NULL DEFAULT '',
f6 UUID NULL,
);
这是我使用的INSERT查询:
INSERT INTO table_a (f1, f2, f3, f4, f5, f6)
SELECT $1, $2, $3, f4, f5, f2
FROM table_a
WHERE <conditionals>
ORDER BY <ordering>
LIMIT 1
基本思想是我寻找满足条件的现有行。如果存在,则使用字段f4,f5和f2填充要插入的新行中的字段f4,f5和f6。如果不存在,那么这些字段应该采用默认值(分别为&#39;&#39;&#39;&#39;和NULL)。
问题是,如果没有找到行,SELECT本身似乎没有返回结果,只是跳过整个插入。如果一行匹配条件,它可以正常工作,但如果该SELECT没有返回任何行则不行。我怎样才能获得理想的行为?
答案 0 :(得分:3)
insert into table_a (f1, f2, f3, f4, f5, f6)
select f1, f2, f3, f4, f5, f6
from (
(
select $1, $2, $3, f4, f5, f2, 1
from table_a
where <conditionals>
order by <ordering>
limit 1
) s
union all
select $1, $2, $3, '', '', null, 2
) s (f1, f2, f3, f4, f5, f6, o)
order by o
limit 1
答案 1 :(得分:1)
如果您想在查询中使用表DDL中的默认值而不是硬编码,则另一种方式:
WITH t AS (
INSERT INTO table_a (f1, f2, f3, f4, f5, f6)
SELECT $1, $2, $3, f4, f5, f2
FROM table_a
WHERE <conditionals>
ORDER BY <ordering>
LIMIT 1
RETURNING *) -- This query will return inserted values
INSERT INTO table_a (f1, f2, f3)
SELECT $1, $2, $3 WHERE (SELECT count(*) FROM t) = 0; -- Insert if no insertion was happened at WITH clause