Postgresql 用于在重复更新时追加插入或插入的合并语法

Postgresql 用于在重复更新时追加插入或插入的合并语法,postgresql,upsert,sql,Postgresql,Upsert,Sql,所以我来自MySQL,我可以做: 但现在我正在使用PostgreSQL,并且正在努力添加UPSERT功能,看起来合并可能会满足我的要求,但我想看看这是否是最理想的语法。我还没有尝试过这个方法,因为我认为MERGE是用来将数据从表1合并到表2的,或者类似的东西可以工作吗 MERGE INTO table USING table ON c = 1 WHEN MATCHED THEN UPDATE SET c=c+1 WHEN NOT MATCHED THEN INSERT

所以我来自MySQL,我可以做:

但现在我正在使用PostgreSQL,并且正在努力添加UPSERT功能,看起来合并可能会满足我的要求,但我想看看这是否是最理想的语法。我还没有尝试过这个方法,因为我认为MERGE是用来将数据从表1合并到表2的,或者类似的东西可以工作吗

MERGE
INTO    table
USING   table
ON      c = 1
WHEN MATCHED THEN
UPDATE
SET     c=c+1
WHEN NOT MATCHED THEN
INSERT  (a,b,c)
VALUES  (1,2,3)
还有其他建议吗

MERGE INTO table
    USING (VALUES (1, 2, 3)) AS newvalues (a, b, c)
    ON table.c = newvalues.c  -- or whatever the PK is
    WHEN MATCHED THEN UPDATE SET c = c + 1
    WHEN NOT MATCHED THEN INSERT (a, b, c)
                              VALUES (newvalues.a, newvalues.b, newvalues.c)
这里的关键是,不要合并到另一个表中,而是使用
using
子句中的
VALUES
构造创建一个常量表源。确切的合并规则,你可以很明显地定制口味

另请参见。

我认为“合并”还没有出现在Postgres中,但应该出现在9.1中

我喜欢用s代替


您链接到的(“插入,重复更新时(postgresql)”)基本上是您提供数据的一些pgsql。我认为该规则更加优雅,因为您不需要显式调用它们,它们在后台透明工作,而不需要在实际插入中调用过程。

在支持合并之前,IMO最简单的方法是将其分解为两个查询:

BEGIN;
  INSERT INTO t (a,b,c) VALUES (1,2,3) WHERE id != 1;
  UPDATE t SET c=c+1 WHERE id = 1;
END;

其中id将被更改为适当的条件。

在合并可用之前,请使用此健壮的方法:

那么这是一个INSERT else IGNORE/SKIP吗?它是一个IGNORE/SKIP,因为您检查是否存在,如果存在,请跳过它。这同样适用于更新操作。将规则视为“一种触发器”,它可以通过重写它或(在这种情况下)忽略部分(或全部)来修改查询本身。我这样做了,但是OLD.ID给出了一个错误,不喜欢这个值。有什么想法吗?这实际上只是一个例子。您可以将任何查询写入where。查看手册中的示例。@PhillPafford显然,插入规则中不存在元行“OLD”,但更新规则中存在。不过还没弄明白…补丁正在“等待作者”-嗯,我喜欢这种方法,尽管它会花费你们两个查询的时间,嗯,在测试中不起作用。在WHERE条件上给我一个错误。支持哪个版本的Postgres?
CREATE OR REPLACE RULE "insert_ignore"
AS ON INSERT TO "table" WHERE
  NEW.id = OLD.id --whatever your conditions are
DO INSTEAD NOTHING;
BEGIN;
  INSERT INTO t (a,b,c) VALUES (1,2,3) WHERE id != 1;
  UPDATE t SET c=c+1 WHERE id = 1;
END;