Release: 1.4.25 | Release Date: September 22, 2021

SQLAlchemy 1.4 Documentation

SQLAlchemy 1.4 / 2.0 Tutorial

此页是 SQLAlchemy 1.4/2.0教程

上一次: 使用核心或ORM选择行 |下一步: |next|

使用核心更新和删除行

到目前为止,我们已经讨论过 Insert ,这样我们就可以将一些数据放入我们的数据库中,然后花费大量时间在 Select 其处理用于从数据库检索数据的广泛的使用模式。在本节中,我们将介绍 UpdateDelete 构造,这些构造用于修改现有行以及删除现有行。本节将从以核心为中心的角度介绍这些构造。

ORM阅读器 -正如在 插入带核心的行 ,即 UpdateDelete 与ORM一起使用时,操作通常从 Session 对象作为 unit of work 进程。

然而,与之不同的是, Insert ,即 UpdateDelete 构造也可以直接与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

多个表删除

喜欢 UpdateDelete 支持在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

从更新、删除获取受影响的行数

两者都有 UpdateDelete 对于使用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

使用返回WITH UPDATE,DELETE

就像 Insert 建造, UpdateDelete 还支持通过使用 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进行数据操作

Previous: 使用核心或ORM选择行 Next: 使用ORM进行数据操作