PostgreSQL 务实应用(二/5)插入冲突
假设我们创建以下月封存表 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 更新的内容与条件则要根据业务规则(如值变化时才更新,或存在则不更新等)具体分析。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |