11

我使用 CTE 编写了一个“upsert”查询,看起来像这样:

WITH
  new_data (id, value) AS (
    VALUES (1, 2), (3, 4), ...
  ),
  updated AS (
    UPDATE table t set
      value = t.value + new_data.value
    FROM new_data
    WHERE t.id = new_data.id
    RETURNING t.*
  )
INSERT INTO table (id, value)
  SELECT id, value
  FROM new_data
  WHERE NOT EXISTS (
    SELECT 1 FROM updated WHERE updated.id = new_data.id
  )

但是,我需要在我的应用程序中使用新值,但此查询不会返回任何内容。添加returning *到插入的末尾将返回所有插入的行,但没有更新的行。

所以,问题是(如何)我可以扩展它以返回更新的行和插入的行?

编辑:当然我可以SELECT在事务中运行它,然后运行它,但是我很想知道是否有单查询方式。

4

1 回答 1

9

尝试类似:

WITH
  new_data (id, value) AS (
    VALUES (1, 2), (3, 4), ...
  ),
  updated AS (
    UPDATE table t set
      value = t.value + new_data.value
    FROM new_data
    WHERE t.id = new_data.id
    RETURNING t.*
  ),
  inserted as (
  INSERT INTO table (id, value)
  SELECT id, value
  FROM new_data
  WHERE NOT EXISTS (
    SELECT 1 FROM updated WHERE updated.id = new_data.id
  )
  RETURNING id, value)
SELECT id, value
FROM inserted 
UNION ALL
SELECT id, value
FROM updated 

顺便说一句,这个查询不是经典的 Postgres upsert。如果有人在进行时同时插入行,它将失败UPDATE table t

于 2013-07-10T16:07:54.140 回答