You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python操作SQLite分组复制去重表时触发Ref列非唯一IntegrityError

SQLite迁移表触发column Ref is not unique报错的原因

报错发生在第一步INSERT执行阶段,后续的删表、重命名语句因为事务回滚根本没有执行,核心原因有三类:

  • 未显式指定字段列表导致列错位
    你使用的INSERT INTO new_table SELECT * FROM old_table写法,完全依赖新旧两张表的字段顺序、字段数量完全一致。如果创建new_table时将Ref字段调整到了第一列作为主键(主键的常见设置位置),和原old_table中Ref的列位置不一致,SELECT返回的列会按原表顺序错位赋值给新表字段,可能将其他存在重复值的列数据写入Ref主键列,直接触发唯一约束冲突。
  • GROUP BY的去重逻辑和新表主键的去重逻辑不一致
    SQLite是柔性类型数据库,这是最容易踩的隐式转换坑:
    • 旧表无字段类型约束,Ref列可能同时存储类型不同但转成字符串后值相同的内容,比如整数10086和字符串'10086'。GROUP BY阶段会因为二者存储类型不同判定为独立值,返回两行数据;但插入新表的VARCHAR(50)类型主键列时,整数会被自动转换为字符串'10086',两个值完全重复触发冲突。
    • 如果新表Ref列配置了大小写不敏感排序规则(如COLLATE NOCASE),或是旧表Ref值存在肉眼不可见的差异(如尾部空格、零宽控制符、全半角字符差异),GROUP BY阶段会将'REF001'和'ref001'、'REF001 '(带尾部空格)判定为不同值返回多行,插入新表时会被判定为重复值,撞主键报错。
  • 历史残留数据干扰
    如果之前运行过失败的迁移脚本,new_table中已经残留了部分导入成功的数据,再次执行INSERT语句时,会因为表内已存在相同Ref值触发冲突。

另外你脚本里的重命名语句本身语法有误,正确的重命名语法是ALTER TABLE new_table RENAME TO old_table;,只是因为INSERT阶段就抛出错误,这段语法问题没有被触发。

迁移脚本修正参考:

conn = connect_to_db("/mnt/wwn-0x5002538e00000000-part1/DATABASE/database.db")
c = conn.cursor()
# 清空new_table可能残留的历史数据
c.execute("DELETE FROM new_table;")
# 显式写全所有字段名,对Ref做强制类型转换保证去重逻辑一致
c.execute("""
INSERT INTO new_table (按新表顺序列全所有26个字段名)
SELECT 按查询顺序列全所有26个对应字段名,其中Ref写为CAST(Ref AS TEXT)
FROM old_table
GROUP BY CAST(Ref AS TEXT)
""")
c.execute("DROP TABLE IF EXISTS old_table;")
c.execute("ALTER TABLE new_table RENAME TO old_table;")
conn.commit()
conn.close()

内容的提问来源于stack exchange,提问作者Rivered

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:06:21