Postgres 9.4.7 INSERT INTO没有ON CONFLICT

时间:2018-01-19 23:56:13

标签: postgresql

我真的想写一个这样的查询:

INSERT INTO test_table (id, dt, amt)
VALUES(4, current_timestamp, 15)
ON CONFLICT (id)
DO UPDATE
    SET dt = VALUES(dt)
        amt = VALUES(amt)

问题是,我使用的Postgres版本(9.4.7)不支持ON CONFLICT结构。如何在不升级Postgres的情况下实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:1)

PostgreSQL 9.4没有任何内置的UPSERT(或MERGE)功能,并且在并发使用时有效地执行它非常困难。

This article discusses the problem in useful detail.

一般来说,您必须在两个选项中进行选择:

  • 重试循环中的单个插入/更新操作;或
  • 锁定表并进行批量合并

如需完整解决方案,请阅读此内容 SO Answer

答案 1 :(得分:-1)

如果你经常这样做。您可以编写一个函数来为您完成。 你可以通过两种方式做到。

  1. 先检查然后插入或更新。
  2. 
        CREATE OR REPLACE FUNCTION insert_test_table(int, timestamp, varchar)
        RETURNS int AS
        $BODY$
        BEGIN
            IF (EXISTS(SELECT id FROM test_table WHERE id = $1)) THEN
                UPDATE test_table SET dt = $2, amt = $3 WHERE id = $1;
                RETURN 2;
            ELSE
                INSERT INTO test_table (id, dt, amt) VALUES($1, $2, $3);
                RETURN 1;
            END IF;
            RETURN 0;
            END;
        $BODY$
        LANGUAGE plpgsql;
    
    1. 使用例外:
    2. 
          CREATE OR REPLACE FUNCTION insert_test_table(int, timestamp, varchar)
          RETURNS int AS
          $BODY$
          BEGIN
              INSERT INTO test_table (id, dt, amt) VALUES($1, $2, $3);
              RETURN 1;
              EXCEPTION WHEN unique_violation THEN 
                      BEGIN
                          UPDATE test_table SET dt = $2, amt = $3 WHERE id = $1;  
                          RETURN 2
                      END;
          END;
          $BODY$
          LANGUAGE plpgsql;
      

      第二种方式可能与其他唯一约束冲突,所以要小心。