关于sql:Postgres:如果不存在则插入,否则返回该行

Postgres: Insert if not exists, otherwise return the row

本问题已经有最佳答案,请猛点这里访问。

在一个SQL语句中,我试图插入一行,如果由于约束而失败,则返回现有行。

我有:

1
INSERT INTO SESSION (token, expiry) SELECT 'abcdefg', '2014-05-14 20:25:12.279667' WHERE  NOT EXISTS (SELECT * FROM SESSION WHERE token= 'abcdefg');

token列有一个唯一的约束。我试过在末尾附加RETURNING *,但这仍然不能返回现有的行。

为什么会这样?我原以为我最后一次的SELECT声明会被执行和归还。有什么想法吗?

注意:由于某些复杂的争用条件,我不能使用Postgres函数或多个SQL语句。


1
2
3
4
5
WITH d(t, e) AS ( VALUES ('abcdefg', '2014-05-14 20:25:12.279667')),
  t AS (SELECT token FROM SESSION, d WHERE token=t),
  i AS (INSERT INTO SESSION (token, expiry)
           SELECT t, e FROM d WHERE t NOT IN (SELECT token FROM t))
SELECT t,e FROM d WHERE t IN (SELECT token FROM t);

查询首先使用要插入的数据生成CTE D

然后在会话中使用与d中的令牌匹配的令牌生成一个CTE T(如果不匹配,则为空)。

然后,如果T中的行不匹配,则使用CTEI将D中的行插入到会话中。

最后,如果在t中有匹配,则返回d中的行。

顺便说一句,这也适用于多行。