想做一个插入更新,但是,Postgresql在9.4版本不支持INSERT ON CONFLICT 求解答,有什么能够替代的吗
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在 PostgreSQL 9.4 版本中,确实尚未引入 INSERT ON CONFLICT
(也称为 UPSERT)这一特性,该特性是在 PostgreSQL 9.5 版本中首次引入的。但是,如果您需要在 9.4 版本中实现类似的功能,可以考虑使用以下几种方法:
使用 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');
使用 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;
$$;
先查询后决定插入或更新:在应用层做逻辑判断,先查询记录是否存在,根据结果决定执行插入还是更新操作。这种方法效率较低,特别是在并发环境下可能会有问题。
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新版本会是更优的选择。