开发者社区 问答 正文

Postgresql在9.4版本不支持INSERT ON CONFLICT 有什么能够替代的吗

想做一个插入更新,但是,Postgresql在9.4版本不支持INSERT ON CONFLICT 求解答,有什么能够替代的吗

展开
收起
CLIFF-程 2019-07-25 14:24:08 907 分享 版权
阿里云 AI 助理回答

在 PostgreSQL 9.4 版本中,确实尚未引入 INSERT ON CONFLICT(也称为 UPSERT)这一特性,该特性是在 PostgreSQL 9.5 版本中首次引入的。但是,如果您需要在 9.4 版本中实现类似的功能,可以考虑使用以下几种方法:

  1. 使用 PL/pgSQL 函数:您可以创建一个PL/pgSQL函数来实现插入或更新逻辑。函数首先尝试插入数据,如果因为唯一约束冲突失败,则执行更新操作。

    CREATE OR REPLACE FUNCTION upsert_table(_id INT, _value TEXT)
    RETURNS VOID AS $$
    BEGIN
     -- 尝试插入
     INSERT INTO your_table(id, value) VALUES (_id, _value);
    
     EXCEPTION WHEN unique_violation THEN
       -- 如果唯一性冲突,则更新
       UPDATE your_table SET value = _value WHERE id = _id;
    END;
    $$ LANGUAGE plpgsql;
    
    -- 调用函数
    SELECT upsert_table(1, 'new_value');
    
  2. 使用 DO 块结合 SAVEPOINT:这是另一种通过PL/pgSQL实现的方法,它利用SAVEPOINT和异常处理来模拟UPSERT行为。

    DO $$
    BEGIN
     -- 尝试插入
     INSERT INTO your_table(id, value) VALUES (1, 'new_value');
    
     EXCEPTION WHEN unique_violation THEN
       -- 如果发生冲突,回滚到SAVEPOINT并执行更新
       ROLLBACK TO SAVEPOINT before_insert;
       UPDATE your_table SET value = 'new_value' WHERE id = 1;
    END;
    $$;
    
  3. 先查询后决定插入或更新:在应用层做逻辑判断,先查询记录是否存在,根据结果决定执行插入还是更新操作。这种方法效率较低,特别是在并发环境下可能会有问题。

    WITH upsert_data AS (
     SELECT * FROM your_table WHERE id = 1 FOR UPDATE
    )
    INSERT INTO your_table(id, value)
    SELECT 1, 'new_value'
    WHERE NOT EXISTS (SELECT 1 FROM upsert_data)
    OR      (SELECT value FROM upsert_data) IS DISTINCT FROM 'new_value';
    
    -- 如果不存在则插入,如果存在且值不同则更新,但此方法在9.4版本可能需要手动分开写成查询+条件分支。
    

请注意,上述方法中的PL/pgSQL函数是推荐的方式,因为它封装了逻辑,并且可以在数据库层面保证事务的一致性。考虑到性能和代码维护性,如果可能的话,升级到支持INSERT ON CONFLICT的PostgreSQL新版本会是更优的选择。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答