PostgreSQL中删除表重复条目并记录用户收藏状态的PL/pgSQL脚本语法错误排查
修复PL/pgSQL脚本中的语法错误并实现预期功能
首先,你遇到的语法错误核心是**INSERT INTO的写法不符合PostgreSQL规范**——PostgreSQL不支持INSERT INTO table FROM ...的语法,必须用INSERT INTO table (列名) SELECT ... FROM ...来填充数据。除此之外,脚本还有几个语法和逻辑问题,我会一步步帮你修复并实现需求:删除WU_MatchingUsers中的重复条目(按IDWU_User1和IDWU_User2分组,保留最新的那条),同时在临时表中记录用户对彼此的收藏状态。
主要问题梳理
INSERT INTO语法错误:必须通过SELECT子句填充数据,而非直接使用FROM- 变量声明位置错误:
DECLARE应该放在BEGIN块的最开头,不能嵌套在内部BEGIN里 IF条件写法错误:不能直接在IF后写SELECT语句,需要先把查询结果存入变量再判断- 冗余循环逻辑:重复计算
ROW_NUMBER()会降低效率,我们可以一次性找出所有要删除的重复记录 DELETE语句中的无效逗号:原脚本里的, "UserAFavoriteTag"是语法错误,应该通过表关联获取收藏状态
修复后的完整脚本
\timing on DO $$ DECLARE duplicate_records RECORD; BEGIN -- 1. 创建临时表,用于记录重复用户对、收藏状态及被删除的记录ID CREATE TEMP TABLE IF NOT EXISTS query ( id SERIAL PRIMARY KEY, idUser1 INT, idUser2 INT, favorite BOOLEAN, deleted_record_id INT ); -- 2. 批量筛选重复记录,关联收藏表获取状态并插入临时表 INSERT INTO query (idUser1, idUser2, favorite, deleted_record_id) SELECT wu.IDWU_User1 AS idUser1, wu.IDWU_User2 AS idUser2, -- 通过左连接判断User1是否收藏了User2,请根据实际表结构调整关联字段 CASE WHEN uaft.id IS NOT NULL THEN TRUE ELSE FALSE END AS favorite, wu.id AS deleted_record_id FROM "WU_MatchingUsers" wu LEFT JOIN "UserAFavoriteTag" uaft ON wu.IDWU_User1 = uaft.user_id AND wu.IDWU_User2 = uaft.favorite_user_id -- 筛选出重复组中除最新(ID最大)之外的所有记录 WHERE wu.id IN ( SELECT id FROM ( SELECT id, ROW_NUMBER() OVER( PARTITION BY IDWU_User1, IDWU_User2 ORDER BY id DESC ) AS row_num FROM "WU_MatchingUsers" ) t WHERE t.row_num > 1 ); -- 3. 批量删除WU_MatchingUsers中的重复条目 DELETE FROM "WU_MatchingUsers" WHERE id IN (SELECT deleted_record_id FROM query); -- 可选:输出删除统计和明细 RAISE NOTICE '已删除 % 条重复记录', (SELECT COUNT(*) FROM query); -- 如需查看每条记录的详情,可取消下面的注释 -- FOR duplicate_records IN SELECT * FROM query LOOP -- RAISE NOTICE '用户ID:% 与 用户ID:%,收藏状态:%,被删除记录ID:%', -- duplicate_records.idUser1, duplicate_records.idUser2, -- duplicate_records.favorite, duplicate_records.deleted_record_id; -- END LOOP; END $$; \timing off
脚本关键说明
- 临时表优化:新增
deleted_record_id字段,方便你追踪被删除的具体记录,后续可按需调整字段。 - 重复记录筛选:用
ROW_NUMBER()窗口函数按用户对分组,按ID降序排序,row_num > 1的就是需要删除的旧重复记录。 - 收藏状态判断:通过
LEFT JOIN关联收藏表,用CASE语句判断是否存在收藏关系——请根据UserAFavoriteTag的实际字段调整关联条件(比如如果表中是user_id和target_user_id,就对应替换)。 - 高效批量操作:一次性完成重复记录的筛选、状态记录和删除,比循环逐条处理效率高得多,适合数据量较大的场景。
注意事项
- 执行前建议先备份数据,或在测试环境验证逻辑,避免误删重要数据。
- 如果不需要追踪被删除的记录ID,可以去掉
deleted_record_id字段,简化临时表结构。
内容的提问来源于stack exchange,提问作者Mathieu Arthur
相关产品推荐
相关产品推荐

