PostgreSQL更新分区重复记录deleted_at时误更新全表问题求助
问题根因
你的语句会更新全表的核心原因是没有在WHERE条件中关联UPDATE的主表和FROM子句的子查询结果。
PostgreSQL的UPDATE ... FROM语法中,如果没有指定主表和FROM来源表的关联条件,数据库会对两个结果集做笛卡尔积匹配:只要子查询中存在RN > 1的记录,主表的每一行都会被判定为匹配命中,最终触发全表更新。
另外原语句的子查询还有两处冗余写法会拖慢性能:
- 子查询中用
SELECT *拉取所有字段没有必要,后续关联只需要用到主键和计算出的RN值即可 - 子查询末尾的
ORDER BY RN DESC对更新逻辑没有任何作用,会增加不必要的排序开销
修正后的语句
注意把语句里的id替换为public.database_tag表实际的主键字段名即可:
UPDATE public.database_tag t SET deleted_at = '2022-04-25 19:33:29.087133+00' FROM ( SELECT id, row_number() OVER (PARTITION BY title ORDER BY created_at) AS RN FROM public.database_tag ) X WHERE t.id = X.id -- 核心关联条件:仅匹配子查询中标记为重复的行 AND X.RN > 1;
操作建议
正式执行更新前,建议先跑以下校验语句,确认返回的记录全是需要标记删除的重复数据,避免误更新:
-- 待更新范围校验 SELECT t.*, X.RN FROM public.database_tag t JOIN ( SELECT id, row_number() OVER (PARTITION BY title ORDER BY created_at) AS RN FROM public.database_tag ) X ON t.id = X.id WHERE X.RN > 1;
内容的提问来源于stack exchange,提问作者Samarth Venkatesh Gowda
相关产品推荐
相关产品推荐

