如果不存在则插入,否则在postgresql中返回id

ari*_*ght 49 postgresql

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

  • id串行主键
  • key varchar
  • value varchar

我已经在SO上看到了这个问题:插入,在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'
    );
Run Code Online (Sandbox Code Playgroud)

它的工作原理是它不存在,如果存在,但我想获得id.是否有"RETURNING id"条款或类似的东西,我可以在那里点击?

Clo*_*eto 79

就在这里 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"
Run Code Online (Sandbox Code Playgroud)

如果已存在,则返回该行

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
Run Code Online (Sandbox Code Playgroud)

如果该行不存在,则将返回已插入的行,而不是现有的行.

顺便说一句,如果对"key"/"value"使其唯一,则它是主键,并且不需要id列.除非"key"/"value"对中的一个或两个都可以为null.

  • 我在仔细检查后意识到这个解决方案实际上并没有做我希望的事情,因为它不会返回任何东西,除非 INSERT 工作(即,如果键值对之前不在表中)。如果该行已经在表中,它只会返回空白(不是预期的 ID)。我之前错过的原因是我在测试时不小心打错了字(因此键值对不在表中,因此它返回了行的 ID)。 (4认同)

Rom*_*kar 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
Run Code Online (Sandbox Code Playgroud)

sql小提琴演示