PostgreSQL中INSERT...ON CONFLICT能否仅返回无冲突的新插入元素?
问题:PostgreSQL中INSERT...ON CONFLICT能否仅返回无冲突的新增条目?
我执行如下向可能存在数据的表插入数据的查询:
INSERT INTO XXX ( ... ) VALUES ( ... ) ON CONFLICT (xxx_id) DO UPDATE SET ( ... ) = ( ... )
想知道PostgreSQL是否支持用RETURNING语句仅返回无冲突的纯新增条目,以此明确区分新增和更新的条目。我知道可以先通过SELECT预校验,但担心数据量变大后性能问题,希望用单查询一次性完成更高效。
解决方案
PostgreSQL支持通过系统字段xmax来区分新增和更新的行,从而实现仅返回无冲突的新增条目:
仅返回新增条目
在原查询的末尾添加带条件的RETURNING子句,利用xmax = 0筛选出纯新增的行(新增行的xmax字段值为0,而被更新的行xmax会被标记为更新事务的ID,不为0):INSERT INTO XXX ( ... ) VALUES ( ... ) ON CONFLICT (xxx_id) DO UPDATE SET ( ... ) = ( ... ) RETURNING * WHERE xmax = 0;同时区分新增与更新条目
如果需要同时获取两种类型的条目并明确标识,可以在RETURNING里新增一个判断字段:INSERT INTO XXX ( ... ) VALUES ( ... ) ON CONFLICT (xxx_id) DO UPDATE SET ( ... ) = ( ... ) RETURNING *, CASE WHEN xmax = 0 THEN 'inserted' ELSE 'updated' END AS operation_type;
这种方式完全在单查询内完成,不需要额外的预校验步骤,避免了数据量大时的性能损耗。
内容的提问来源于stack exchange,提问作者Virthuss
相关产品推荐
相关产品推荐

