postgresql 编写Postgres获取或创建SQL查询

hsgswve4  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(5)|浏览(293)

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

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

i34xakig

i34xakig1#

在SQL DBMS中,选择-测试-插入方法是错误的:没有什么可以阻止另一个进程在您的selectinsert语句之间插入“missing”行。请执行以下操作:

INSERT INTO mytable (color, brightness, size, age)
SELECT color, brightness, size, age 
FROM mytable
WHERE NOT EXISTS (
    SELECT 1
    FROM mytable
    WHERE color = 'X' AND brightness = 'Y'
);
SELECT (color, brightness, size, age) 
FROM mytable 
WHERE color = 'X' AND brightness= 'Y';

您应该能够将整个文本作为单个“查询”传递给DBMS。您可能需要考虑将其制作为存储过程。

jgzswidk

jgzswidk2#

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
6fe3ivhb

6fe3ivhb3#

在这里添加我的解决方案。它与@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 or create”的“get”部分!如果值已经存在,则不会发生任何事情。
语句末尾的并集确保了如果没有插入值(因为它已经存在),我们仍然从表中检索该值。

c8ib6hqw

c8ib6hqw4#

如果您的列参与唯一索引约束,则可以使用自9.5版起可用的方法:

INSERT INTO mytable (color, brightness, size, age)
VALUES ('X', 'Y', 'big', 'old')
ON CONFLICT (color) DO NOTHING;

(假设您在color上有唯一索引)。
文档位于:postgresql 9.5

ql3eal8s

ql3eal8s5#

你可以这样简化它。

INSERT INTO table (col1, col2, col3) 
VALUES (val1, val2, val3)
ON
 CONFLICT conflict_target conflict_action;

相关问题