使用SQLAlchemy中的bulk_update_mappings更新具有不同值的多个行

Lym*_*rga 16 python mysql sqlalchemy

我有两张桌子Foo和Bar.我刚刚x在Bar表中添加了一个新列,它必须使用Foo中的值填充

class Foo(Base):
    __table__ = 'foo'
    id = Column(Integer, primary_key=True)
    x = Column(Integer, nullable=False)

class Bar(Base):
    __table__ = 'bar'
    id = Column(Integer, primary_key=True)
    x = Column(Integer, nullable=False)
    foo_id = Column(Integer, ForeignKey('foo.id'), nullable=False)
Run Code Online (Sandbox Code Playgroud)

一种直接的方法是迭代Bar中的所有行,然后逐个更新它们,但需要很长时间(Foo和Bar中有超过100k行)

for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    b.x = foo_x
session.flush()
Run Code Online (Sandbox Code Playgroud)

现在我想知道这是否是正确的方法 -

mappings = []
for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    info = {'id':b.id, 'x': foo_x}
    mappings.append(info)
session.bulk_update_mappings(Bar, mappings)
Run Code Online (Sandbox Code Playgroud)

那里没有太多的例子bulk_update_mappings.文档建议

所有存在且不属于主键的键都应用于UPDATE语句的SET子句; 必需的主键值应用于WHERE子句.

那么,在这种情况下id将在WHERE子句中使用,然后使用x字典中的值进行更新吧?

Tar*_*ani 12

该方法在使用方面是正确的.我唯一要改变的就是下面的内容

mappings = []
i = 0

for b, foo_x in session.query(Bar, Foo.x).join(Foo, Foo.id==Bar.foo_id):
    info = {'id':b.id, 'x': foo_x}
    mappings.append(info)
    i = i + 1
    if i % 10000 == 0:
        session.bulk_update_mappings(Bar, mappings)
        session.flush()
        session.commit()
        mappings[:] = []

session.bulk_update_mappings(Bar, mappings)
Run Code Online (Sandbox Code Playgroud)

这将确保您没有太多数据挂在内存中,并且您不会一次性对数据库进行太大的插入