如何用execute批量插入多行?executemany事务一致性疑问咨询
批量插入变量数据 + 避免部分插入的解决方案
一、用executemany()实现多行插入(无需硬编码值)
不管你用的是Python里的sqlite3、psycopg2还是mysql-connector这类DB-API兼容库,实现批量插入都很直接。核心就是用占位符代替具体值,然后把你的scores变量直接传给executemany()就行。
先举个实际例子:假设你要插入的表是student_scores,有user_id和score两个字段,scores是一个包含元组的列表(比如scores = [(101, 92), (102, 88), (103, 95)],数量随便多少都可以)。
不同数据库的占位符语法略有不同:
- SQLite用
? - PostgreSQL用
%s - MySQL一般用
%s或者?
下面是通用的代码模板,你换成自己的数据库库就行:
import sqlite3 # 替换成你实际用的库,比如psycopg2 # 建立连接 conn = sqlite3.connect('your_database.db') cursor = conn.cursor() # 写带占位符的插入语句,不用写具体值 insert_sql = "INSERT INTO student_scores (user_id, score) VALUES (?, ?)" # 直接把scores传给executemany,搞定批量插入 cursor.executemany(insert_sql, scores) # 这步别忘!后面会说为什么重要 conn.commit() # 收尾工作 cursor.close() conn.close()
这样不管scores里有10条还是1000条数据,都能一次性插入,完全不用硬编码任何值。
二、程序崩溃时会不会出现部分插入?必须用事务解决!
答案是:如果不做额外处理,大概率会有部分插入的风险!
很多人容易忽略事务的重要性。这里给你理清楚:
- 大多数DB-API库默认是「非自动提交」模式,也就是说,你执行的所有操作都在一个事务里,只有调用
commit()才会把所有修改真正写到数据库。但如果程序在executemany()执行中途崩溃,而你还没调用commit(),那数据库会自动回滚这个事务,不会有任何数据残留——这看起来没问题? - 但要注意:有些数据库驱动对
executemany()的实现是把批量数据拆成多个单独的插入请求发送给数据库。如果你的程序刚好在这些请求发送的中途崩溃,而数据库刚好开启了自动提交(有些场景下会这样),那已经发送的请求就会被单独提交,导致部分数据插入成功,剩下的失败。
所以最稳妥的方式是手动用事务+异常处理来保证「要么全插成功,要么全不插」,完全规避部分插入的风险。
修改上面的代码,加上事务和异常处理:
import sqlite3 conn = sqlite3.connect('your_database.db') cursor = conn.cursor() insert_sql = "INSERT INTO student_scores (user_id, score) VALUES (?, ?)" try: # 执行批量插入 cursor.executemany(insert_sql, scores) # 只有当所有插入都成功时,才提交事务 conn.commit() print("所有数据插入成功!") except Exception as e: # 只要中间出任何错,就回滚事务,保证数据库回到操作前的状态 conn.rollback() print(f"插入失败,已回滚所有操作: {str(e)}") finally: # 不管成功失败,都要关闭游标和连接 cursor.close() conn.close()
举个极端场景:如果scores有500条数据,executemany()执行到第200条时程序突然崩溃了——因为我们用了事务+异常处理,这200条数据不会被保留,数据库还是原来的样子。
最后总结
- 用
executemany(插入SQL语句, scores)就能实现批量插入,完全不用硬编码值,scores里的数量随便多少都支持 - 必须通过事务(配合
commit()和rollback())来保证原子性,彻底避免程序崩溃时的部分插入问题
内容的提问来源于stack exchange,提问作者Baz
相关产品推荐
相关产品推荐

