编写Postgres获取或创建SQL查询

时间:2013-04-20 18:50:33

标签: sql postgresql

我想编写一个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);

有没有办法将这些组合成一个查询?

4 个答案:

答案 0 :(得分:21)

在SQL DBMS中,select-test-insert方法是一个错误:没有什么可以阻止另一个进程在selectinsert语句之间插入“缺失”行。这样做:

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" "获取或创建"的一部分!如果该值已存在,则不会发生任何事情。

语句末尾的联合确保如果未插入值(因为它已经存在),我们仍然从表中检索该值。