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

Insert if not exists, else return id in postgresql

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

  • ID系列主键
  • 密钥VARCHAR
  • 价值VARCHAR

我已经在这里看到这个问题了:在postgresql中插入,在重复更新时?但我想知道,如果ID存在,如何获取它,而不是更新它。如果标准实践总是"插入"或"如果存在则更新",为什么会这样?执行选择(限制1)的成本是否大于执行更新?

我有以下代码

1
2
3
4
5
6
7
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"子句或类似的东西可以在里面点击?


是的,有EDOCX1[0]

1
2
3
4
5
6
7
8
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"

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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列。除非"key"/"value"对中的一个或两个都可以为空。


1
2
3
4
5
6
7
8
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小提琴演示


您可以存储返回到变量的值,形式为…返回field1,field2,…变为var1,var2,…

如果不使用返回的结果集在plpgsql中调用查询,则返回的查询通常会返回错误"query has no destination for result data"。