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

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

  • id串行主键
  • key varchar
  • 值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' ); 

它的工作原理是它不插入,如果存在,但我想要得到的ID。 有没有“RETURNING ID”条款或类似的东西,我可以在那里?

是的,正在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 

如果行不存在,则返回插入的行。

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

 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小提琴演示

您可以将返回值的forms存储到… RETURNING field1,field2,… INTO var1,var2,…

如果在不使用返回的结果集的情况下在plpgsql中调用它,RETURNING通常会返回一个将返回错误“query has no destination for result data”的查询。