存在一个表Users,在我的代码中我有一个用户对象的大列表。要插入它们,我可以使用:
session.add_all(user_list)
session.commit()
问题是可能有几个重复项,我想更新,但数据库不允许插入重复项。当然,我可以迭代user_list并尝试在数据库中插入用户,如果失败,则更新:
for u in users:
q = session.query(T).filter(T.fullname==u.fullname).first()
if q:
session.query(T).filter_by(index=q.index).update({column: getattr(u,column) for column in Users.__table__.columns.keys() if column!='id'})
session.commit()
else:
session.add(u)
session.commit()
但我发现这个解决方案非常无效:首先,我提出了几个检索对象q的请求,而不是批量插入新项目,而是逐个插入。我想知道是否有更好的解决方案来完成这项任务。
UPD更好的版本:
for u in users:
q = session.query(T).filter(Users.fullname==u.fullname).first()
if q:
for column in Users.__table__.columns.keys():
if not column=='index':
setattr(q,column,getattr(u,column))
session.add(q)
else:
session.add(u)
session.commit()
更好的解决方案是使用
INSERT ... ON DUPLICATE KEY UPDATE ...
bulkMySQL构造(我认为您使用的是MySQL,因为您的帖子带有"MySQL"标签)。通过这种方式,您可以在一个语句/事务中插入新条目并更新现有条目,请参阅http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html
如果您有多个唯一索引,并且根据您的模式,您必须填写所有not NULL值(因此在调用它之前发出一个批量SELECT),这并不理想,但这绝对是最有效的选项,我们经常使用它。批量版本看起来像(假设name
是一个唯一的密钥):
INSERT INTO User (name, phone, ...) VALUES
('ksmith', '111-11-11', ...),
('jford', '222-22,22', ...),
...,
ON DUPLICATE KEY UPDATE
phone = VALUES(phone),
... ;
不幸的是,INSERT ... ON DUPLICATE KEY UPDATE ...
不是SQLa本机支持的,因此您必须实现一个小的助手函数,它将为您构建查询。