如何在Posgres 9.5中使用带有WITH cluase的upsert时检索插入行的id?

时间:2016-08-18 09:11:15

标签: sql postgresql postgresql-9.5

我正在尝试使用“WITH”

在Postgres 9.5中进行扰乱查询
with s as (
            select id
            from products
            where product_key = 'test123'
        ), i as (
            insert into products (product_key, count_parts)
            select 'test123', 33
            where not exists (select 1 from s)
            returning id                       
        )
        update products
        set product_key='test123', count_parts=33
        where id = (select id from s) 
        returning id

显然我只在更新时检索id,并且即使我知道插入成功,也无法获取插入内容。

我需要以一种方式修改此查询,我将能够在插入和更新时获取id。

谢谢!

1 个答案:

答案 0 :(得分:1)

我不清楚你为什么选择WITH第一次SELECT,但你只返回UPDATE id的原因是因为你没有选择INSERT返回。

正如评论中提到的那样(和链接),Postgres 9.5支持INSERT ON CONFLICT子句,这是一种更清晰的使用方法。

9.5之前和之后的一些例子:

9.5之前:使用WITH

的常用方法
WITH    u AS (
            UPDATE      products
            SET         product_key='test123', count_parts=33
            WHERE       product_key = 'test123'
            RETURNING   id
        ),i AS (
            INSERT
            INTO        products ( product_key, count_parts )
            SELECT      'test123', 33
            WHERE       NOT EXISTS( SELECT 1 FROM u )
            RETURNING   id
        )
SELECT  *
FROM    (       SELECT id FROM u
        UNION   SELECT id FROM i
        ) r;

9.5之后:使用INSERT .. ON CONFLICT

INSERT INTO products ( product_key, count_parts )
VALUES      ( 'test123', 33 )
ON CONFLICT ( product_key ) DO
UPDATE
SET         product_key='test123', count_parts=33
RETURNING   id;

<强>更新

正如评论中暗示的那样,使用INSERT .. ON CONFLICT方式可能会有轻微的缺点。
如果使用自动增量表并且此查询发生很多,那么WITH可能是更好的选择。
查看更多:https://stackoverflow.com/a/39000072/1161463