Postgres 9.4.7 INSERT INTO without ON CONFLICT
本问题已经有最佳答案,请猛点这里访问。
我真的想写一个这样的查询:
1 2 3 4 5 6 | 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)不支持冲突上的构造。关于如何在不升级Postgres的情况下实现这一点有什么想法吗?
PostgreSQL 9.4没有任何内置的upsert(或merge)功能,并且在面对并发使用时高效地完成这项工作非常困难。
本文详细讨论了这个问题。
通常,您必须在两个选项之间进行选择:
- 重试循环中的单个插入/更新操作;或
- 锁定表并进行批合并
要获得完整的解决方案,请阅读此所以回答
如果你经常这样做。你可以写一个函数来为你做这件事。你可以通过两种方式来做到。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 3 4 5 6 7 8 9 10 11 12 13 14 | 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; |
第二种方法可能与其他独特的约束冲突,所以要小心。