PostgreSQL如何使用“ON CONFLICT”子句语义插入行

3
在PostgreSQL中是否有一种简单的方法来执行与SQLite中以下内容相当的操作?
INSERT INTO foo (x, y, z) VALUES (1, 2, 3) ON CONFLICT replace;

我找了很多解决方案,但发现它们都需要使用复杂的自定义函数。另一个解决我的问题的方法是只需执行以下操作:

delete from foo where x=1; INSERT INTO foo (x, y, z) VALUES (1, 2, 3) ON CONFLICT replace;

虽然语义上不完全相同,但对于我的情况可以使用。

如果不需要自定义函数,我更喜欢使用ON CONFLICT规则。


2
可能是 [在插入时更新(PostgreSQL)] 的重复问题 (https://dev59.com/uHNA5IYBdhLWcg3wC5Xh)。 - Frank Farmer
长话短说,没有。在Postgres中,没有简单的语法来实现这个。 - Frank Farmer
我看到了那个问题。他的情况想要进行插入或更新。我需要进行插入或替换。 - Falmarri
答案是一样的。在Postgres中,没有简单的语法,您将不得不使用过程/多个查询。 - Frank Farmer
2个回答

4

从PostgreSQL 9.1版本开始(此时为beta版本),您可以使用公共表达式来执行插入或替换操作:

/**
CREATE TABLE foo(id serial primary key, content text unique);
**/

WITH replace AS (
    DELETE FROM foo
    WHERE
        content = 'bar'
    RETURNING content
)
INSERT INTO 
    foo(content) -- values:
SELECT
    *
FROM replace RIGHT JOIN (SELECT CAST('bar' AS text) as content) sub USING(content);

'bar'是将要插入或替换的值。

在旧版本中不起作用,你需要等待 :-(


3
请注意,如果不获取表级别锁,这在并发情况下是不安全的 - Craig Ringer

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接