如何为已有SQLite表添加主键并高效迁移数据?
解决SQLite新增主键表批量插入的高效方案
针对你遇到的问题——不用手动指定109个字段,高效把原表数据导入带主键的新表,我给你几个实用的解决思路:
方法1:利用SQLite内置rowid和表结构查询自动生成字段列表
SQLite的每个表都自带隐式的rowid(唯一非空),而且可以通过系统查询获取原表的所有字段名,不用手动敲109个字段:
- 先执行这条查询,获取原表
fp的所有字段名(逗号分隔):
SELECT GROUP_CONCAT(name, ', ') FROM PRAGMA table_info(fp);
执行后会得到类似 col1, col2, ..., col109 的字符串。
- 把这个字符串代入下面的INSERT语句,用原表的
rowid作为新表的id值:
INSERT INTO fp_new (id, [这里替换成上面得到的字段列表]) SELECT rowid, * FROM fp;
这样就完美匹配了新表的110列(id+109个原字段),而且全程不用手动输入所有字段名。
方法2:用脚本分批插入(适合大表,避开递归限制)
如果担心一次性插入50万条数据性能问题,或者不想手动复制字段列表,可以用Python/Shell等脚本自动处理,同时分批插入避免递归触发器的限制:
比如用Python的sqlite3库写个简单脚本:
import sqlite3 # 连接数据库 conn = sqlite3.connect('你的数据库文件名.db') cursor = conn.cursor() # 获取原表的所有字段名 cursor.execute("PRAGMA table_info(fp)") fp_columns = [col[0] for col in cursor.fetchall()] column_str = ', '.join(fp_columns) # 获取总记录数 cursor.execute("SELECT COUNT(*) FROM fp") total = cursor.fetchone()[0] # 分批插入,每次处理1000条 batch_size = 1000 offset = 0 while offset < total: insert_sql = f""" INSERT INTO fp_new (id, {column_str}) SELECT rowid, * FROM fp LIMIT ? OFFSET ? """ cursor.execute(insert_sql, (batch_size, offset)) conn.commit() offset += batch_size print(f"已插入 {offset}/{total} 条记录") conn.close()
这个脚本会自动读取原表结构,分批插入数据,全程无需手动干预,而且性能稳定。
方法3:纯SQL分批插入(无需外部脚本)
如果想用纯SQL解决,可以用递归CTE生成批次偏移量,分批处理数据(同样需要先获取字段列表):
-- 先获取字段列表,替换下面的[字段列表] WITH RECURSIVE batches(off) AS ( SELECT 0 UNION ALL SELECT off + 1000 FROM batches WHERE off + 1000 <= (SELECT COUNT(*) FROM fp) ) INSERT INTO fp_new (id, [字段列表]) SELECT f.rowid, f.* FROM fp f WHERE f.rowid > batches.off AND f.rowid <= batches.off + 1000 CROSS JOIN batches;
这个方法通过递归生成0、1000、2000...的偏移量,每次处理1000条数据,避开了SQLite的递归深度限制。
关键提醒
原表的rowid是SQLite自动维护的唯一标识符,用来作为新表的id主键是完全安全的,不用担心重复或空值问题。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

