如何使用SQLAlchemy将字典列表批量插入SQLite数据库
现有代码问题修正指南
核心现存Bug梳理
- 循环变量名不匹配:循环遍历的变量命名为
d,但循环体内取值时引用了不存在的变量i,运行时会触发NameError。 - 模型实例复用问题:在循环外仅创建了一个
Keys类实例,循环过程中反复修改该实例的属性值,SQLAlchemy Session会将这个对象识别为同一条记录的状态变更,最终提交时只会写入一条带最后一次属性值的记录,也就是你观察到的只存最后一条数据的现象。 - 代码缩进不符合Python语法规范:原代码中
create_key函数内部的代码块没有统一的缩进层级,运行时会触发缩进错误。
修正方案1:逐次新建模型实例(直观易理解)
核心逻辑是每遍历一条生成的密钥字典,就新建一个独立的Keys模型实例,不要在循环外提前创建复用:
from sqlalchemy import Column, Integer, String from sqlalchemy.orm import Session from fastapi import Request, Form, Depends # 数据库模型定义 class Keys(Base): __tablename__ = "keys" id = Column(Integer, primary_key=True) project = Column(String) key_id = Column(Integer) key = Column(String) def create_key( request: Request, project: str = Form(...), amount: int = Form(...), db: Session = Depends(get_db) ): data_generated = streamticket.thekeygenerator.keydata.generator(amount, project) for item in data_generated: # 每循环一次生成一个完全独立的模型实例 new_key = Keys( project=item["project"], key_id=item["key_id"], key=item["key"] ) db.add(new_key) # 所有实例添加完成后统一提交 db.commit()
这种写法下,每个
new_key对象都有独立的内存标识,Session会将它们识别为待写入数据库的独立行,提交时不会出现数据覆盖的问题。
修正方案2:用add_all批量写入(适合大批量数据场景)
如果需要生成的密钥量较大,用批量添加的方式可以减少和Session的交互次数,提升写入性能,实现时先把所有模型实例收集为列表,一次性传入add_all方法:
def create_key( request: Request, project: str = Form(...), amount: int = Form(...), db: Session = Depends(get_db) ): data_generated = streamticket.thekeygenerator.keydata.generator(amount, project) # 批量收集所有待写入的模型实例 keys_to_insert = [ Keys( project=item["project"], key_id=item["key_id"], key=item["key"] ) for item in data_generated ] # 一次性将列表中的所有实例交给Session跟踪 db.add_all(keys_to_insert) db.commit()
补充注意事项
- 不要在循环外提前创建模型实例:哪怕中途重置属性值,只要是同一个实例对象,Session始终只会跟踪这一个对象的状态,不会生成多行独立记录。
- 如果单次要生成的密钥量超过数千条,可以采用分批提交的方式(比如每收集1000条数据就提交一次),避免单次事务过大导致的数据库连接超时问题。
内容的提问来源于stack exchange,提问作者Stig Runar Solli
相关产品推荐
相关产品推荐

