61

我在 PostgreSQL 中有一个简单的表,它包含三列:

  • id 序列主键
  • 关键变量
  • 值 varchar

我已经在这里看到了这个问题:Insert, on duplicate update in PostgreSQL? 但我想知道如果它存在,如何获取 id,而不是更新。如果标准做法是始终“插入”或“如果存在则更新”,这是为什么呢?执行 SELECT (LIMIT 1) 的成本是否大于执行 UPDATE?

我有以下代码

INSERT INTO tag
    ("key", "value")
    SELECT 'key1', 'value1'
WHERE
    NOT EXISTS (
        SELECT id,"key","value" FROM tag WHERE key = 'key1' AND value = 'value1'
    );

从某种意义上说,如果存在它就不会插入,但我想获取 id。是否有“返回 id”子句或类似的东西,我可以在那里点击?

4

3 回答 3

90

就在这里returning

INSERT INTO tag ("key", "value")
SELECT 'key1', 'value1'
WHERE NOT EXISTS (
    SELECT id, "key", "value"
    FROM node_tag
    WHERE key = 'key1' AND value = 'value1'
    )
returning id, "key", "value"

如果该行已存在,则返回该行

with s as (
    select id, "key", "value"
    from tag
    where key = 'key1' and value = 'value1'
), i as (
    insert into tag ("key", "value")
    select 'key1', 'value1'
    where not exists (select 1 from s)
    returning id, "key", "value"
)
select id, "key", "value"
from i
union all
select id, "key", "value"
from s

如果该行不存在,它将返回插入的行,否则返回现有的行。

顺便说一句,如果“key”/“value”对使它唯一,那么它就是主键,不需要 id 列。除非“键”/“值”对中的一个或两个可以为空。

于 2013-08-12T17:14:58.703 回答
6
with vals as (
  select 'key5' as key, 'value2' as value
)
insert into Test1 (key, value)
select v.key, v.value
from vals as v
where not exists (select * from Test1 as t where t.key = v.key and t.value = v.value)
returning id

sql 小提琴演示

于 2013-08-12T17:30:03.803 回答
-1

并且您可以将返回的值存储到变量中... RETURNING field1, field2,... INTO var1, var2,...

RETURNING 通常会返回一个查询,如果您在 plpgsql 中调用它而不使用其返回的结果集,该查询将返回错误“查询没有结果数据的目的地”。

于 2013-11-08T01:48:05.297 回答