我想编写一个Postgres SQL语句,说明寻找具有颜色X和亮度Y的用户。如果该用户存在,则返回其所有行数据。如果没有,请创建一个新行并传递其他信息。这两个单独的陈述会做这样的事情:
Select (color, brightness, size, age) FROM mytable WHERE color = 'X' AND brightness= 'Y';
如果没有返回任何内容,请执行以下命令:
INSERT INTO mytable (color, brightness, size, age) VALUES (X, Y, big, old);
有没有办法将这些组合成一个查询?
答案 0 :(得分:21)
在SQL DBMS中,select-test-insert方法是一个错误:没有什么可以阻止另一个进程在select
和insert
语句之间插入“缺失”行。这样做:
insert into mytable (color, brightness, size, age)
select color, brightness, size, age
from mytable
where not exists (
select 1 from
from mytable
where color = 'X' and brightness = 'Y'
);
SELECT (color, brightness, size, age)
FROM mytable
WHERE color = 'X' AND brightness= 'Y';
您应该能够将整个文本作为单个“查询”传递给DBMS。您可能需要考虑将其变为存储过程。
答案 1 :(得分:5)
with sel as (
select color, brightness, size, age
from mytable
where color = 'X' and brightness = 'Y'
), ins as (
insert into mytable (color, brightness, size, age)
select 'X', 'Y', 6.2, 40
where not exists (
select 1 from sel
)
returning color, brightness, size, age
)
select color, brightness, size, age
from ins
union
select color, brightness, size, age
from sel
答案 2 :(得分:3)
如果您的列参与唯一索引约束,则可以使用自9.5版以来可用的方法:
INSERT INTO mytable (color, brightness, size, age)
VALUES ('X', 'Y', 'big', 'old')
ON CONFLICT (color) DO NOTHING;
(假设您在color
上有唯一索引)。
文档是gere:https://www.postgresql.org/docs/9.5/static/sql-insert.html
答案 3 :(得分:1)
在此处添加我的解决方案。它与@Clodoaldo Neto和@ astef的解决方案有点不同。
WITH ins AS (
INSERT INTO mytable (color, brightness, size, age)
VALUES ('X', 'Y', 'big', 'old')
ON CONFLICT (color) DO NOTHING
RETURNING *
)
SELECT * FROM ins
UNION
SELECT * FROM mytable
WHERE color = 'X';
我发现astef的解决方案不适合我的目的:它没有执行" get" "获取或创建"的一部分!如果该值已存在,则不会发生任何事情。
语句末尾的联合确保如果未插入值(因为它已经存在),我们仍然从表中检索该值。