假设我们创建以下月封存表 month_stat,字段 month_name 表示月份,字段 total_count 表示统计数字。
CREATE TABLE month_stat (month_name varchar(6), total_count int, UNIQUE (month_name));
普通处理
假设数据到达,我们用 v_month_name 表示到达数据的月份,v_count 表示本次到达的数量,则通常我们使用以下方式完成月封存数据的记录:
DO $$
DECLARE
v_month_name varchar := '201904'; -- 本次数据的月份
v_count int := 3; -- 本次数据相关的数量
BEGIN
-- 如果月份已经存在,则更新统计,将数量累加上去
IF EXISTS (SELECT 1 FROM month_stat WHERE month_name = v_month_name FOR UPDATE) THEN
UPDATE month_stat set total_count = total_count + v_count
WHERE month_name = v_month_name;
ELSE
-- 插入月份,数量为本次数量
INSERT INTO month_stat (month_name, total_count) VALUES (v_month_name, v_count);
END IF;
END $$;
判断逻辑在 BEGIN 与 END 之间,先判断月份是否存在,再按分支进行更新或插入处理。
使用 ON CONFLECT
好消息是,从 postgres-9.5 起增加了插入冲突的支持:
INSERT … ON CONFLICT DO nothing/UPDATE
于是有了以下写法:
INSERT INTO month_stat (month_name, total_count)
VALUES ('201904', 3)
ON CONFLICT(month_name)
DO
UPDATE set total_count = month_stat.total_count + EXCLUDED.total_count;
CONFLICT 后边括号中必须是建立了唯一索引(或主键)的字段或字段集。
DO 后边可以是 nothing 表示冲突时忽略,什么都不做。也可以是 UPDATE,表示冲突时需要更新,本次冲突相关的数据使用 EXCLUDED 来引用。
使用 ON CONFILECT 至少有两个好处:
至于使用 nothing 还是 UPDATE,以及 UPDATE 更新的内容与条件则要根据业务规则(如值变化时才更新,或存在则不更新等)具体分析。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。