使用核心更新和删除行
SQLAlchemy 1.4 / 2.0 Tutorial
此页是 SQLAlchemy 1.4/2.0教程 。
上一次: 使用核心或ORM选择行 |下一步: |next|
使用核心更新和删除行
到目前为止,我们已经讨论过 Insert
,这样我们就可以将一些数据放入我们的数据库中,然后花费大量时间在 Select
其处理用于从数据库检索数据的广泛的使用模式。在本节中,我们将介绍 Update
和 Delete
构造,这些构造用于修改现有行以及删除现有行。本节将从以核心为中心的角度介绍这些构造。
ORM阅读器 -正如在 插入带核心的行 ,即 Update
和 Delete
与ORM一起使用时,操作通常从 Session
对象作为 unit of work 进程。
然而,与之不同的是, Insert
,即 Update
和 Delete
构造也可以直接与ORM一起使用,使用一种称为“支持ORM的更新和删除”的模式;因此,熟悉这些构造对于ORM的使用很有用。这两种使用方式都在各节中进行了讨论。 更新ORM对象 和 删除ORM对象 。
update()SQL表达式构造
这个 update()
函数会生成 Update
它表示SQL中的UPDATE语句,它将更新表中的现有数据。
就像 insert()
构造,有一种“传统”形式的 update()
,它一次针对一个表发出UPDATE,并且不返回任何行。但是,一些后端支持可以一次修改多个表的UPDATE语句,并且UPDATE语句还支持返回,以便匹配行中包含的列可以在结果集中返回。
基本更新如下::
>>> from sqlalchemy import update >>> stmt = ( ... update(user_table).where(user_table.c.name == 'patrick'). ... values(fullname='Patrick the Star') ... ) >>> print(stmt) UPDATE user_account SET fullname=:fullname WHERE user_account.name = :name_1
这个 Update.values()
方法控制UPDATE语句的Set元素的内容。这与 Insert
构造。通常可以使用列名作为关键字参数来传递参数。
UPDATE支持所有主要的SQL形式的UPDATE,包括针对表达式的UPDATE,我们可以使用 Column
表达式::
>>> stmt = ( ... update(user_table). ... values(fullname="Username: " + user_table.c.name) ... ) >>> print(stmt) UPDATE user_account SET fullname=(:name_1 || user_account.name)
为了在“ecutemany”上下文中支持UPDATE,在该上下文中,将针对同一语句调用多个参数集, bindparam()
构造可用于设置绑定参数;这些参数替换了文本值通常所在的位置:
>>> from sqlalchemy import bindparam >>> stmt = ( ... update(user_table). ... where(user_table.c.name == bindparam('oldname')). ... values(name=bindparam('newname')) ... ) >>> with engine.begin() as conn: ... conn.execute( ... stmt, ... [ ... {'oldname':'jack', 'newname':'ed'}, ... {'oldname':'wendy', 'newname':'mary'}, ... {'oldname':'jim', 'newname':'jake'}, ... ] ... ) BEGIN (implicit) UPDATE user_account SET name=? WHERE user_account.name = ? [...] (('ed', 'jack'), ('mary', 'wendy'), ('jake', 'jim')) <sqlalchemy.engine.cursor.CursorResult object at 0x...> COMMIT
可应用于更新的其他技术包括:
相关更新
UPDATE语句可以通过使用 correlated subquery 。可以在可能放置列表达式的任何位置使用子查询::
>>> scalar_subq = ( ... select(address_table.c.email_address). ... where(address_table.c.user_id == user_table.c.id). ... order_by(address_table.c.id). ... limit(1). ... scalar_subquery() ... ) >>> update_stmt = update(user_table).values(fullname=scalar_subq) >>> print(update_stmt) UPDATE user_account SET fullname=(SELECT address.email_address FROM address WHERE address.user_id = user_account.id ORDER BY address.id LIMIT :param_1)
UPDATE..FROM
一些数据库(如PostgreSQL和MySQL)支持语法“update from”,其中附加表可以直接在特殊的FROM子句中声明。当其他表位于语句的WHERE子句中时,将隐式生成此语法::
>>> update_stmt = ( ... update(user_table). ... where(user_table.c.id == address_table.c.user_id). ... where(address_table.c.email_address == 'patrick@aol.com'). ... values(fullname='Pat') ... ) >>> print(update_stmt) UPDATE user_account SET fullname=:fullname FROM address WHERE user_account.id = address.user_id AND address.email_address = :email_address_1
还有一种特定于MySQL的语法可以更新多个表。这就需要我们参考 Table
VALUES子句中的对象,以便引用其他表:
>>> update_stmt = ( ... update(user_table). ... where(user_table.c.id == address_table.c.user_id). ... where(address_table.c.email_address == 'patrick@aol.com'). ... values( ... { ... user_table.c.fullname: "Pat", ... address_table.c.email_address: "pat@aol.com" ... } ... ) ... ) >>> from sqlalchemy.dialects import mysql >>> print(update_stmt.compile(dialect=mysql.dialect())) UPDATE user_account, address SET address.email_address=%s, user_account.fullname=%s WHERE user_account.id = address.user_id AND address.email_address = %s
参数有序更新
另一个仅限MySQL的行为是,UPDATE的SET子句中参数的顺序实际上会影响每个表达式的计算。对于此用例, Update.ordered_values()
方法接受元组序列,以便可以控制此顺序 2:
>>> update_stmt = ( ... update(some_table). ... ordered_values( ... (some_table.c.y, 20), ... (some_table.c.x, some_table.c.y + 10) ... ) ... ) >>> print(update_stmt) UPDATE some_table SET y=:y, x=(some_table.y + :y_1)
- 2
而Python字典是 guaranteed to be insert ordered 从Python3.7开始,
Update.ordered_values()
当MySQL UPDATE语句的SET子句必须以特定方式进行时,方法仍然提供了一种额外的意图清晰度度量。
delete()SQL表达式构造
这个 delete()
函数会生成 Delete
它表示SQL中的DELETE语句,它将从表中删除行。
这个 delete()
从API的角度来看,语句非常类似于 update()
构造,传统上不返回行,但允许在某些数据库后端上返回变体。
>>> from sqlalchemy import delete >>> stmt = delete(user_table).where(user_table.c.name == 'patrick') >>> print(stmt) DELETE FROM user_account WHERE user_account.name = :name_1
多个表删除
喜欢 Update
, Delete
支持在WHERE子句中使用相关子查询以及特定于后端的多个表语法,例如 DELETE FROM..USING
在MySQL上::
>>> delete_stmt = ( ... delete(user_table). ... where(user_table.c.id == address_table.c.user_id). ... where(address_table.c.email_address == 'patrick@aol.com') ... ) >>> from sqlalchemy.dialects import mysql >>> print(delete_stmt.compile(dialect=mysql.dialect())) DELETE FROM user_account USING user_account, address WHERE user_account.id = address.user_id AND address.email_address = %s
从更新、删除获取受影响的行数
两者都有 Update
和 Delete
对于使用Core调用的语句,支持在语句继续执行后返回匹配的行数 Connection
,即 Connection.execute()
。根据下面提到的注意事项,可以从 CursorResult.rowcount
属性:
>>> with engine.begin() as conn: ... result = conn.execute( ... update(user_table). ... values(fullname="Patrick McStar"). ... where(user_table.c.name == 'patrick') ... ) ... print(result.rowcount) BEGIN (implicit) UPDATE user_account SET fullname=? WHERE user_account.name = ? [...] ('Patrick McStar', 'patrick') 1 COMMIT
小技巧
这个 CursorResult
类是的子类 Result
它包含特定于DBAPI的附加属性 cursor
对象。方法调用语句时,将返回此子类的实例 Connection.execute()
方法。使用ORM时, Session.execute()
方法为所有INSERT、UPDATE和DELETE语句返回此类型的对象。
关于以下方面的事实 CursorResult.rowcount
:
返回的值是行数 匹配的 通过语句的WHERE子句。行是否被实际修改并不重要。
CursorResult.rowcount
不一定可用于使用返回的UPDATE或DELETE语句。对于 executemany 处决,
CursorResult.rowcount
也可能不可用,这在很大程度上取决于正在使用的DBAPI模块以及配置的选项。该属性CursorResult.supports_sane_multi_rowcount
指示此值是否可用于当前使用的后端。某些驱动程序(特别是非关系数据库的第三方方言)可能不支持
CursorResult.rowcount
完全没有。这个CursorResult.supports_sane_rowcount
会表明这一点。ORM使用“rowcount” unit of work 验证UPDATE或DELETE语句是否与预期行数匹配的过程,也是文档中记录的ORM版本控制功能所必需的 配置版本计数器 。
使用返回WITH UPDATE,DELETE
就像 Insert
建造, Update
和 Delete
还支持通过使用 Update.returning()
和 Delete.returning()
方法。当在支持返回的后端上使用这些方法时,从与语句的WHERE条件匹配的所有行中选择的列将在 Result
对象作为可以迭代的行::
>>> update_stmt = ( ... update(user_table).where(user_table.c.name == 'patrick'). ... values(fullname='Patrick the Star'). ... returning(user_table.c.id, user_table.c.name) ... ) >>> print(update_stmt) UPDATE user_account SET fullname=:fullname WHERE user_account.name = :name_1 RETURNING user_account.id, user_account.name >>> delete_stmt = ( ... delete(user_table).where(user_table.c.name == 'patrick'). ... returning(user_table.c.id, user_table.c.name) ... ) >>> print(delete_stmt) DELETE FROM user_account WHERE user_account.name = :name_1 RETURNING user_account.id, user_account.name
进一步阅读以更新、删除
参见
更新/删除接口文档:
启用ORM的更新和删除:
SQLAlchemy 1.4 / 2.0 Tutorial
下一教程部分: 使用ORM进行数据操作