SQLite全列重复行删除及CSV导入主键约束错误处理
1. 如何删除SQLite中所有列(含ID列)均重复的数据行?
在SQLite里处理全列重复的行,核心思路是先识别重复组,再保留每组中的一行、删除其余重复项。因为SQLite默认给每个表分配了ROWID(除非你创建了WITHOUT ROWID表),我们可以借助它来区分内容完全相同的行。
方法一:使用窗口函数(SQLite 3.25.0+支持)
窗口函数是最直观的实现方式,通过ROW_NUMBER()给每个重复组的行编号,然后删除编号大于1的重复行:
WITH duplicate_groups AS ( SELECT *, -- 按所有列分组,给每组行按ROWID排序编号 ROW_NUMBER() OVER ( PARTITION BY C1, C2, ..., C15 -- 替换为你的所有列名 ORDER BY ROWID ) AS row_num FROM Book1 ) DELETE FROM Book1 WHERE ROWID IN (SELECT ROWID FROM duplicate_groups WHERE row_num > 1);
PARTITION BY后必须列出表中所有列,确保只有当所有列内容都相同时才被归为一组。这里我们保留每组中ROWID最小的行,删除其他重复行。
方法二:自连接+分组(兼容旧版SQLite)
如果你的SQLite版本不支持窗口函数,可以用子查询分组取最小ROWID的方式实现:
DELETE FROM Book1 WHERE ROWID NOT IN ( SELECT MIN(ROWID) FROM Book1 GROUP BY C1, C2, ..., C15 -- 同样替换为所有列名 );
逻辑和方法一一致:按所有列分组,每组仅保留ROWID最小的那一行,其余重复行全部删除。
2. 解决临时表重复ID导致插入永久表主键约束错误的问题
根据你的描述,问题根源是临时表Book1中存在重复的C15值(对应永久表的RunId主键),导致插入时触发主键冲突。你可以选择先清理临时表的重复数据,或者直接在插入时处理重复,两种方案如下:
方案一:先清理临时表的重复ID,再插入
如果需要保留干净的临时表,先删除重复的ID行(这里假设只要C15重复就会引发冲突,无需考虑其他列):
-- 清理临时表:每个C15仅保留最早插入的一行 DELETE FROM Book1 WHERE ROWID NOT IN ( SELECT MIN(ROWID) FROM Book1 GROUP BY C15 ); -- 插入到永久表 INSERT INTO permanent_table (RunId, col1, col2, ...) -- 替换为永久表的列名 SELECT C15, col1, col2, ... FROM Book1; -- 对应临时表的列
如果需要确保所有列都重复才删除(而非仅ID重复),可以复用第一个问题中的全列分组方法。
方案二:插入时直接去重,无需修改临时表
如果你不需要保留去重后的临时表,可以直接在插入语句中处理重复,省去删除步骤:
- 用
DISTINCT过滤全列重复的行:
INSERT INTO permanent_table (RunId, col1, col2, ...) SELECT DISTINCT C15, col1, col2, ... FROM Book1;
- 或者按
C15分组,选择每组中某一行的数据(比如用MAX/MIN提取其他列的值):
INSERT INTO permanent_table (RunId, col1, col2, ...) SELECT C15, MAX(col1), MAX(col2), ... -- 根据需求选择MAX/MIN FROM Book1 GROUP BY C15;
这种方式适合你只关心RunId唯一,其他列可保留任意一行的场景。
内容的提问来源于stack exchange,提问作者Behrooz Karjoo




