有效批次"更新或插入"在SqlAlchemy中

时间:2015-11-25 17:53:12

标签: python mysql sqlalchemy

存在一个表用户,在我的代码中,我有一个很大的User对象列表。要插入它们,我可以使用:

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()

1 个答案:

答案 0 :(得分:0)

更好的解决方案是使用

  INSERT ... ON DUPLICATE KEY UPDATE ...

批量 MySQL构造(我假设您正在使用MySQL,因为您的帖子标记为' mysql')。这样您就可以在一个语句/事务中插入新条目并更新现有条目,请参阅http://dev.mysql.com/doc/refman/5.6/en/insert-on-duplicate.html

如果您有多个唯一索引,并且根据您的架构,您必须填写所有NOT NULL值(因此在调用它之前发出一个批量SELECT),这不是理想的,但它&# 39;绝对是最有效的选择,我们经常使用它。批量版本看起来像(让我们假设name是一个唯一的密钥):

  INSERT INTO User (name, phone, ...) VALUES
    ('ksmith', '111-11-11', ...),
    ('jford', '222-22,22', ...),
    ...,
  ON DUPLICATE KEY UPDATE
    phone = VALUES(phone),
    ... ;

不幸的是,SQLA本身不支持INSERT ... ON DUPLICATE KEY UPDATE ...,因此您必须实现一个小帮助函数,它将为您构建查询。