几个月前,我从一个关于堆栈溢出的回答中学到了如何使用以下语法在MySQL中一次执行多个更新:

INSERT INTO table (id, field, field2) VALUES (1, A, X), (2, B, Y), (3, C, Z)
ON DUPLICATE KEY UPDATE field=VALUES(Col1), field2=VALUES(Col2);

我现在切换到PostgreSQL,显然这是不对的.它指的是所有正确的表,所以我认为这是使用不同关键字的问题,但我不确定PostgreSQL文档中在哪里涉及到了这一点.

为了澄清,我想插入一些东西,如果它们已经存在,请更新它们.

推荐答案

自9.5版以来,PostgreSQL有UPSERT种语法,其中101 clause.种语法如下(类似于MySQL)

INSERT INTO the_table (id, column_1, column_2) 
VALUES (1, 'A', 'X'), (2, 'B', 'Y'), (3, 'C', 'Z')
ON CONFLICT (id) DO UPDATE 
  SET column_1 = excluded.column_1, 
      column_2 = excluded.column_2;

在postgresql的邮箱组存档中搜索"upsert",可以找到an example of doing what you possibly want to do, in the manual个:

Example 38-2. Exceptions with UPDATE/INSERT

本例使用异常处理来执行更新或插入(视情况而定):

CREATE TABLE db (a INT PRIMARY KEY, b TEXT);

CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
    LOOP
        -- first try to update the key
        -- note that "a" must be unique
        UPDATE db SET b = data WHERE a = key;
        IF found THEN
            RETURN;
        END IF;
        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO db(a,b) VALUES (key, data);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- do nothing, and loop to try the UPDATE again
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');

可能有一个例子说明了如何批量执行此操作,使用9.1及以上版本中的CTE,在hackers mailing list中:

WITH foos AS (SELECT (UNNEST(%foo[])).*)
updated as (UPDATE foo SET foo.a = foos.a ... RETURNING foo.id)
INSERT INTO foo SELECT foos.* FROM foos LEFT JOIN updated USING(id)
WHERE updated.id IS NULL;

请参见a_horse_with_no_name's answer以获得更清晰的示例.

Postgresql相关问答推荐

将real[]数组作为完整的浮点值从postquist返回

函数返回查询执行plpgsql时不存在列

PostgreSQL解释分析实际时间不加总

如何在Postgres中对分区表使用Hibernate验证?

如何在postgres中测试锁定

在插入时创建一个触发器,在PostgreSQL中的另一个表上创建另一个触发器

返回行值和行计数的总和

为什么不能超过 10 个并发连接到 Postgres RDS 数据库

postgres 中的模式前缀,被调用元素的范围

连接 Supbase Postgresql 数据库时,Stepzen Graphiql 资源管理器中的主机名解析错误

如何将 NULL 值插入 UUID 而不是零

PostgreSQL错误致命:角色 username不存在

在 PostgreSQL docker 镜像中创建表

SELECT INTO 具有多个归因

在 PostgreSQL 中表示Sparse稀疏数据

在 postgreSQL 中更改序列名称

如何增加 max_locks_per_transaction

有没有办法确保 WHERE 子句在 DISTINCT 之后发生?

错误:关系列不存在 PostgreSQL,无法运行插入查询

PostgreSQL - 必须出现在 GROUP BY 子句中或在聚合函数中使用