使用WHERE在SQLAlchemy Core中进行批量更新

52 投票
5 回答
77079 浏览
提问于 2025-04-20 02:35

我已经成功地在SQLAlchemy中使用批量插入,像这样:

conn.execute(addresses.insert(), [ 
   {'user_id': 1, 'email_address' : 'jack@yahoo.com'},
   {'user_id': 1, 'email_address' : 'jack@msn.com'},
   {'user_id': 2, 'email_address' : 'www@www.org'},
   {'user_id': 2, 'email_address' : 'wendy@aol.com'},
])

现在我需要一个类似的功能来更新数据。我尝试了这个:

conn.execute(addresses.insert(), [ 
   {'user_id': 1, 'email_address' : 'jack@yahoo.com', 'id':12},
   {'user_id': 1, 'email_address' : 'jack@msn.com', 'id':13},
   {'user_id': 2, 'email_address' : 'www@www.org', 'id':14},
   {'user_id': 2, 'email_address' : 'wendy@aol.com', 'id':15},
])

我希望每一行都能根据'id'字段进行更新,但它并没有生效。我猜这可能是因为我没有指定WHERE条件,但我不知道如何用字典中的数据来指定这个WHERE条件。

有人能帮我吗?

5 个回答

0

根据上面的回答,我成功解决了问题,因为SQLAlchemy(一个数据库工具)说我需要加上synchronize_session=None这个参数。

我用以下代码做出了正确的处理。

values= {"id" : results.id, "user_id": results.id}
        if user.email is not None:
            values['email'] = user.email
        if user.first_name is not None:
            values['first_name'] = user.first_name

        if user.last_name is not None:
            values['last_name'] = user.last_name
        else:
            values['last_name'] = results.last_name
update_user_q = update(u).where(u.id == bindparam("user_id")).values(
                            email=bindparam("email"),
                            first_name=bindparam("first_name"), last_name=bindparam("last_name")).execution_options(
                            synchronize_session=None)
            db.execute(update_user_q, [
                values]
                )
            db.commit()

别忘了在你的数据中传入主键。

3

@Jongbin Park 的解决方案确实对我有用,特别是在使用复合主键的情况下。(这是在 Azure SQL Server 上)

update_vals = []
update_vals.append(dict(Name='name_a', StartDate='2020-05-26 20:17:32', EndDate='2020-05-26 20:46:03', Comment='TEST COMMENT 1'))
update_vals.append(dict(Name='name_b', StartDate='2020-05-26 21:31:16', EndDate='2020-05-26 21:38:37', Comment='TEST COMMENT 2'))
s.bulk_update_mappings(MyTable, update_vals)
s.commit()

这里的 Name、StartDate 和 EndDate 都是复合主键的一部分。'Comment' 是要在数据库中更新的值。

4

在2023年,SQLAlchemy 2.0 更新了它的接口

from sqlalchemy import update
session.execute(
    update(User),
    [
        {"id": 1, "fullname": "Spongebob Squarepants"},
        {"id": 3, "fullname": "Patrick Star"},
        {"id": 5, "fullname": "Eugene H. Krabs"},
    ],
)
34

这个会话里有两个功能,分别叫做 bulk_insert_mappingsbulk_update_mappings。你可以在这里找到相关的 文档

需要注意的是,在使用这些功能时,你必须在映射中提供主键。

# List of dictionary including primary key
user_mappings = [{
    'user_id': 1, # This is pk?
    'email_address': 'jack@yahoo.com',
    '_id': 1
}, ...]

session.bulk_update_mappings(User, user_mappings)
session.commit()
89

请阅读使用Core更新和删除行这个教程部分。下面的代码可以帮助你入门:

from sqlalchemy import bindparam
stmt = addresses.update().\
    where(addresses.c.id == bindparam('_id')).\
    values({
        'user_id': bindparam('user_id'),
        'email_address': bindparam('email_address'),
    })

conn.execute(stmt, [
    {'user_id': 1, 'email_address' : 'jack@yahoo.com', '_id':1},
    {'user_id': 1, 'email_address' : 'jack@msn.com', '_id':2},
    {'user_id': 2, 'email_address' : 'www@www.org', '_id':3},
    {'user_id': 2, 'email_address' : 'wendy@aol.com', '_id':4},
])

撰写回答