ORM 查询指南
本节概述了使用SQLAlchemy ORM发出查询的方法 2.0 style 用法。
本节的读者应该熟悉 SQLAlchemy 1.4/2.0教程 ,特别是这里的大部分内容都是在 使用核心或ORM选择行 .
选择语句
SELECT语句由 select()
返回一个 Select
对象:
>>> from sqlalchemy import select >>> stmt = select(User).where(User.name == 'spongebob')
调用 Select
通过ORM,它被传递到 Session.execute()
::
sql>>> result = session.execute(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account WHERE user_account.name = ? [...] ('spongebob',) >>> for user_obj in result.scalars(): ... print(f"{user_obj.name} {user_obj.fullname}") spongebob Spongebob Squarepants
选择ORM实体和属性
这个 select()
construct接受ORM实体,包括映射类以及表示映射列的类级属性,这些属性被转换为ORM注释 FromClause
和 ColumnElement
施工时的构件。
A Select
包含ORM注释实体的对象通常使用 Session
对象,而不是 Connection
对象,以使与ORM相关的特性生效,包括返回ORM映射对象的实例。当使用 Connection
直接地说,结果行只包含列级别的数据。
下面我们从 User
实体,产生 Select
从映射的 Table
向哪个 User
已映射::
sql>>> result = session.execute(select(User).order_by(User.id)) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account ORDER BY user_account.id [...] ()
从ORM实体中选择时,实体本身在结果中作为具有单个元素的行返回,而不是一系列单独的列;例如,上面的 Result
退货 Row
对象,这些对象每行只有一个元素,该元素保持在 User
对象::
>>> result.fetchone() (User(id=1, name='spongebob', fullname='Spongebob Squarepants'),)
选择包含ORM实体的单元素行列表时,通常会跳过生成 Row
对象,而不是直接接收ORM实体,这是使用 Result.scalars()
方法:
>>> result.scalars().all() [User(id=2, name='sandy', fullname='Sandy Cheeks'), User(id=3, name='patrick', fullname='Patrick Star'), User(id=4, name='squidward', fullname='Squidward Tentacles'), User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')]
ORM实体在结果行中根据它们的类名命名,例如下面我们从两者中选择 User
和 Address
同时:
>>> stmt = select(User, Address).join(User.addresses).order_by(User.id, Address.id) sql>>> for row in session.execute(stmt): ... print(f"{row.User.name} {row.Address.email_address}") SELECT user_account.id, user_account.name, user_account.fullname, address.id AS id_1, address.user_id, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id ORDER BY user_account.id, address.id [...] () spongebob spongebob@sqlalchemy.org sandy sandy@sqlalchemy.org sandy squirrel@squirrelpower.org patrick pat999@aol.com squidward stentcl@sqlalchemy.org
选择单个属性
映射类上的属性,例如 User.name
和 Address.email_address
,具有与实体类本身类似的行为,例如 User
在传递给 select()
. 它们的使用方式与表列的使用方式相同:
sql>>> result = session.execute( ... select(User.name, Address.email_address). ... join(User.addresses). ... order_by(User.id, Address.id) ... ) SELECT user_account.name, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id ORDER BY user_account.id, address.id [...] ()
ORM属性,它们本身被称为 InstrumentedAttribute
对象,可以与任何 ColumnElement
,和以相同的方式在结果行中传递,例如下面我们在每行中按列名引用它们的值:
>>> for row in result: ... print(f"{row.name} {row.email_address}") spongebob spongebob@sqlalchemy.org sandy sandy@sqlalchemy.org sandy squirrel@squirrelpower.org patrick pat999@aol.com squidward stentcl@sqlalchemy.org
将选定的属性与绑定分组
这个 Bundle
construct是一个可扩展的仅限ORM的构造,它允许将一组列表达式分组到结果行中:
>>> from sqlalchemy.orm import Bundle >>> stmt = select( ... Bundle("user", User.name, User.fullname), ... Bundle("email", Address.email_address) ... ).join_from(User, Address) sql>>> for row in session.execute(stmt): ... print(f"{row.user.name} {row.email.email_address}") SELECT user_account.name, user_account.fullname, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id [...] () spongebob spongebob@sqlalchemy.org sandy sandy@sqlalchemy.org sandy squirrel@squirrelpower.org patrick pat999@aol.com squidward stentcl@sqlalchemy.org
这个 Bundle
对于创建轻量级视图以及自定义列分组(如映射)可能很有用。
参见
列束 -在ORM加载文档中。
选择ORM别名
如本教程所述 使用别名 ,可以使用 aliased()
针对映射类构造:
>>> from sqlalchemy.orm import aliased >>> u1 = aliased(User) >>> print(select(u1).order_by(u1.id)) SELECT user_account_1.id, user_account_1.name, user_account_1.fullname FROM user_account AS user_account_1 ORDER BY user_account_1.id
当使用 Table.alias()
,SQL别名是匿名命名的。对于从具有显式名称的行中选择实体的情况 aliased.name
也可以传递参数::
>>> from sqlalchemy.orm import aliased >>> u1 = aliased(User, name="u1") >>> stmt = select(u1).order_by(u1.id) sql>>> row = session.execute(stmt).first() SELECT u1.id, u1.name, u1.fullname FROM user_account AS u1 ORDER BY u1.id [...] () >>> print(f"{row.u1.name}") spongebob
这个 aliased
构造也是在ORM中使用子查询的核心;节 联接到子查询 进一步讨论。
从文本和核心语句获取ORM结果
ORM支持从来自其他源的SELECT语句加载实体。典型的用例是文本SELECT语句,在SQLAlchemy中,它使用 text()
构造。这个 text()
construct一旦被构造,就可以使用语句将加载的ORM映射列的相关信息进行扩充;然后可以将这些信息与ORM实体本身相关联,以便基于该语句加载ORM对象。
给定一个文本SQL语句,我们希望从中加载:
>>> from sqlalchemy import text >>> textual_sql = text("SELECT id, name, fullname FROM user_account ORDER BY id")
我们可以通过使用 TextClause.columns()
方法;当调用此方法时 TextClause
对象转换为 TextualSelect
对象,它承担的角色与 Select
构建。这个 TextClause.columns()
方法通常被传递 Column
对象或等效对象,在这种情况下,我们可以在 User
直接上课:
>>> textual_sql = textual_sql.columns(User.id, User.name, User.fullname)
我们现在有了一个ORM配置的SQL结构,可以分别加载“id”、“name”和“fullname”列。将此SELECT语句用作 User
相反,我们可以将这些列链接到启用了ORM的常规ORM Select
使用 Select.from_statement()
方法:
>>> # using from_statement() >>> orm_sql = select(User).from_statement(textual_sql) >>> for user_obj in session.execute(orm_sql).scalars(): ... print(user_obj) SELECT id, name, fullname FROM user_account ORDER BY id [...] () User(id=1, name='spongebob', fullname='Spongebob Squarepants') User(id=2, name='sandy', fullname='Sandy Cheeks') User(id=3, name='patrick', fullname='Patrick Star') User(id=4, name='squidward', fullname='Squidward Tentacles') User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')
相同的 TextualSelect
对象也可以使用 TextualSelect.subquery()
方法,并链接到 User
使用 aliased()
按照下文中讨论的类似方式进行施工 联接到子查询 ::
>>> # using aliased() to select from a subquery >>> orm_subquery = aliased(User, textual_sql.subquery()) >>> stmt = select(orm_subquery) >>> for user_obj in session.execute(stmt).scalars(): ... print(user_obj) SELECT anon_1.id, anon_1.name, anon_1.fullname FROM (SELECT id, name, fullname FROM user_account ORDER BY id) AS anon_1 [...] () User(id=1, name='spongebob', fullname='Spongebob Squarepants') User(id=2, name='sandy', fullname='Sandy Cheeks') User(id=3, name='patrick', fullname='Patrick Star') User(id=4, name='squidward', fullname='Squidward Tentacles') User(id=5, name='ehkrabs', fullname='Eugene H. Krabs')
使用 TextualSelect
直接与 Select.from_statement()
与利用 aliased()
在前一种情况下,结果SQL中不生成子查询。从性能或复杂性的角度来看,这在某些情况下可能是有利的。
参见
使用INSERT、UPDATE和ON CONFLICATION(即upsert)返回ORM对象 -The Select.from_statement()
方法也适用于 DML 支持返回的语句。
联接
这个 Select.join()
和 Select.join_from()
方法用于根据SELECT语句构造SQL联接。
本节将详细介绍这些方法的ORM用例。有关从核心角度对其使用的一般概述,请参阅 显式FROM子句和连接 在 SQLAlchemy 1.4/2.0教程 .
用法 Select.join()
在ORM上下文中 2.0 style 查询与 Query.join()
方法在 1.x style 查询。
简单关系联接
考虑两个类之间的映射 User
和 Address
,有关系 User.addresses
表示的集合 Address
与每个关联的对象 User
. 最常见的用法是 Select.join()
是沿着此关系创建联接,使用 User.addresses
属性作为如何发生这种情况的指示器::
>>> stmt = select(User).join(User.addresses)
在上面的什么地方,呼叫 Select.join()
沿着 User.addresses
将导致SQL大约相当于:
>>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address ON user_account.id = address.user_id
在上面的例子中,我们提到 User.addresses
传到 Select.join()
作为“on子句”,也就是说,它指示连接的“on”部分应该如何构造。
链接多个连接
构造一个连接链,多个 Select.join()
可以使用呼叫。relationship-bound属性同时表示连接的左侧和右侧。考虑其他实体 Order
和 Item
那里 User.orders
关系是指 Order
实体,以及 Order.items
关系是指 Item
实体,通过关联表 order_items
. 二 Select.join()
将加入来自第一个调用的结果 User
到 Order
,还有一秒钟 Order
到 Item
. 但是,自从 Order.items
是一个 many to many 关系中,它将生成两个单独的JOIN元素,结果SQL中总共有三个JOIN元素:
>>> stmt = ( ... select(User). ... join(User.orders). ... join(Order.items) ... ) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN user_order ON user_account.id = user_order.user_id JOIN order_items AS order_items_1 ON user_order.id = order_items_1.order_id JOIN item ON item.id = order_items_1.item_id
每次调用 Select.join()
方法的重要性仅限于我们希望从中连接的内容的“左”端需要在我们指示新目标之前出现在from列表中。 Select.join()
例如,如果我们指定 select(User).join(Order.items).join(User.orders)
,并将引发错误。在正确的实践中 Select.join()
方法的调用方式与我们希望如何呈现SQL中的JOIN子句一致,并且每个调用都应该表示与它前面的内容之间的清晰链接。
我们在FROM子句中目标的所有元素都可以作为继续从连接的潜在点。我们可以继续添加其他元素从 User
上面的实体,例如在 User.addresses
与我们的连接链的关系:
>>> stmt = ( ... select(User). ... join(User.orders). ... join(Order.items). ... join(User.addresses) ... ) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN user_order ON user_account.id = user_order.user_id JOIN order_items AS order_items_1 ON user_order.id = order_items_1.order_id JOIN item ON item.id = order_items_1.item_id JOIN address ON user_account.id = address.user_id
联接到目标实体或可选
第二种形式 Select.join()
允许将任何映射实体或核心可选构造作为目标。在这种用法中, Select.join()
会尝试 推断 JOIN的ON子句,使用两个实体之间的自然外键关系:
>>> stmt = select(User).join(Address) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address ON user_account.id = address.user_id
在上面的通话表中, Select.join()
被要求自动推断“on子句”。如果没有,则此调用窗体最终将引发一个错误 ForeignKeyConstraint
两者之间的设置映射 Table
如果有多个 ForeignKeyConstraint
它们之间的界限使得要使用的适当约束是不明确的。
注解
当利用 Select.join()
或 Select.join_from()
在不指示ON子句的情况下,配置了ORM relationship()
构造是 不考虑在内 . 仅配置 ForeignKeyConstraint
映射级别的实体之间的关系 Table
当试图为联接推断ON子句时,将查询对象。
用ON子句联接到目标
第三个调用形式允许显式传递目标实体和ON子句。包含SQL表达式作为ON子句的示例如下:
>>> stmt = select(User).join(Address, User.id==Address.user_id) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address ON user_account.id = address.user_id
基于子句的表达式也可以是关系绑定属性;此形式实际上声明 Address
两次,但这是可以接受的:
>>> stmt = select(User).join(Address, User.addresses) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address ON user_account.id = address.user_id
如果我们在别名实体中使用上述语法,那么它的功能就更强大了。的默认目标 User.addresses
是 Address
类,但是如果我们使用 aliased()
, the aliased()
表单将用作目标,如下例所示:
>>> a1 = aliased(Address) >>> a2 = aliased(Address) >>> stmt = ( ... select(User). ... join(a1, User.addresses). ... join(a2, User.addresses). ... where(a1.email_address == 'ed@foo.com'). ... where(a2.email_address == 'ed@bar.com') ... ) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address AS address_1 ON user_account.id = address_1.user_id JOIN address AS address_2 ON user_account.id = address_2.user_id WHERE address_1.email_address = :email_address_1 AND address_2.email_address = :email_address_2
使用关系绑定属性时,还可以使用别名实体替换目标实体 PropComparator.of_type()
方法。使用此方法的相同示例为:
>>> stmt = ( ... select(User). ... join(User.addresses.of_type(a1)). ... join(User.addresses.of_type(a2)). ... where(a1.email_address == 'ed@foo.com'). ... where(a2.email_address == 'ed@bar.com') ... ) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address AS address_1 ON user_account.id = address_1.user_id JOIN address AS address_2 ON user_account.id = address_2.user_id WHERE address_1.email_address = :email_address_1 AND address_2.email_address = :email_address_2
扩充内置ON子句
作为在现有关系条件下提供完整定制的替代品 PropComparator.and_()
函数可以应用于relationship属性以将附加条件扩充到ON子句中;附加条件将使用AND与默认条件组合。下面,ON标准介于 user_account
和 address
包含由连接的两个独立元素 AND
,第一个是沿着外键的自然连接,第二个是自定义限制条件:
>>> stmt = ( ... select(User). ... join(User.addresses.and_(Address.email_address != 'foo@bar.com')) ... ) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN address ON user_account.id = address.user_id AND address.email_address != :email_address_1
参见
这个 PropComparator.and_()
方法也适用于装入器策略。参见章节 向加载程序选项添加条件 举个例子。
联接到子查询
连接的目标可以是任何“可选”的实体,其中有效地包括子单元。使用ORM时,这些目标通常是用 aliased()
构造,但这不是严格要求的,尤其是在结果中未返回联接实体时。例如,从 User
实体到 Address
实体,其中 Address
实体表示为行限制的子查询,我们首先构造一个 Subquery
对象使用 Select.subquery()
,然后可以将其用作 Select.join()
方法:
>>> subq = ( ... select(Address). ... where(Address.email_address == 'pat999@aol.com'). ... subquery() ... ) >>> stmt = select(User).join(subq, User.id == subq.c.user_id) >>> print(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account JOIN (SELECT address.id AS id, address.user_id AS user_id, address.email_address AS email_address FROM address WHERE address.email_address = :email_address_1) AS anon_1 ON user_account.id = anon_1.user_id
当通过调用时,上面的SELECT语句 Session.execute()
将返回包含 User
实体,但不是 Address
实体。为了增加 Address
实体到将在结果集中返回的实体集,我们构造一个 aliased()
反对 Address
实体和自定义子查询。注意,我们还应用了一个名称 "address"
到 aliased()
构造,以便在结果行中按名称引用它:
>>> address_subq = aliased(Address, subq, name="address") >>> stmt = select(User, address_subq).join(address_subq) >>> for row in session.execute(stmt): ... print(f"{row.User} {row.address}") SELECT user_account.id, user_account.name, user_account.fullname, anon_1.id AS id_1, anon_1.user_id, anon_1.email_address FROM user_account JOIN (SELECT address.id AS id, address.user_id AS user_id, address.email_address AS email_address FROM address WHERE address.email_address = ?) AS anon_1 ON user_account.id = anon_1.user_id [...] ('pat999@aol.com',) User(id=3, name='patrick', fullname='Patrick Star') Address(id=4, email_address='pat999@aol.com')
对于表示多个实体的子查询,同一个子查询也可以由多个实体引用。子查询本身在语句中将保持唯一,而链接到它的实体使用 aliased
参考不同的列集合:
>>> user_address_subq = ( ... select(User.id, User.name, Address.id, Address.email_address). ... join_from(User, Address). ... where(Address.email_address.in_(['pat999@aol.com', 'squirrel@squirrelpower.org'])). ... subquery() ... ) >>> user_alias = aliased(User, user_address_subq, name="user") >>> address_alias = aliased(Address, user_address_subq, name="address") >>> stmt = select(user_alias, address_alias).where(user_alias.name == 'sandy') >>> for row in session.execute(stmt): ... print(f"{row.user} {row.address}") SELECT anon_1.id, anon_1.name, anon_1.id_1, anon_1.email_address FROM (SELECT user_account.id AS id, user_account.name AS name, address.id AS id_1, address.email_address AS email_address FROM user_account JOIN address ON user_account.id = address.user_id WHERE address.email_address IN (?, ?)) AS anon_1 WHERE anon_1.name = ? [...] ('pat999@aol.com', 'squirrel@squirrelpower.org', 'sandy') User(id=2, name='sandy', fullname='Sandy Cheeks') Address(id=3, email_address='squirrel@squirrelpower.org')
控制加入内容
如果当前状态的左侧 Select
不符合我们想加入的目标 Select.join_from()
可使用的方法:
>>> stmt = select(Address).join_from(User, User.addresses).where(User.name == 'sandy') >>> print(stmt) SELECT address.id, address.user_id, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id WHERE user_account.name = :name_1
这个 Select.join_from()
方法接受两个或三个参数,格式为 <join from>, <onclause>
或 <join from>, <join to>, [<onclause>]
::
>>> stmt = select(Address).join_from(User, Address).where(User.name == 'sandy') >>> print(stmt) SELECT address.id, address.user_id, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id WHERE user_account.name = :name_1
为SELECT设置初始FROM子句,以便 Select.join()
可以在以后使用 Select.select_from()
也可以使用以下方法:
>>> stmt = select(Address).select_from(User).join(Address).where(User.name == 'sandy') >>> print(stmt) SELECT address.id, address.user_id, address.email_address FROM user_account JOIN address ON user_account.id = address.user_id WHERE user_account.name = :name_1
小技巧
这个 Select.select_from()
方法实际上并不对FROM子句中表的顺序拥有最终决定权。如果该语句还引用 Join
构造,该构造以不同的顺序引用现有表,则 Join
构造优先。当我们使用像这样的方法时 Select.join()
和 Select.join_from()
,这些方法最终会创建这样一个 Join
对象。因此我们可以看到 Select.select_from()
在类似以下情况下被覆盖::
>>> stmt = select(Address).select_from(User).join(Address.user).where(User.name == 'sandy') >>> print(stmt) SELECT address.id, address.user_id, address.email_address FROM address JOIN user_account ON user_account.id = address.user_id WHERE user_account.name = :name_1
在上面的位置,我们看到FROM子句是 address JOIN user_account
,即使我们声明 select_from(User)
第一。因为 .join(Address.user)
方法调用时,该语句最终等同于以下内容:
>>> user_table = User.__table__ >>> address_table = Address.__table__ >>> from sqlalchemy.sql import join >>> >>> j = address_table.join(user_table, user_table.c.id == address_table.c.user_id) >>> stmt = ( ... select(address_table).select_from(user_table).select_from(j). ... where(user_table.c.name == 'sandy') ... ) >>> print(stmt) SELECT address.id, address.user_id, address.email_address FROM address JOIN user_account ON user_account.id = address.user_id WHERE user_account.name = :name_1
这个 Join
构造作为另一个条目添加到 Select.select_from()
取代上一条目的列表。
特殊关系运算符
详见 SQLAlchemy 1.4/2.0教程 在 在查询中使用关系 ,ORM属性映射 relationship()
可以以多种方式用作SQL构造助手。除上述文件外 联接 ,关系也可能生成要在WHERE子句中使用的条件。请参阅下面的链接部分。
参见
中的节 使用相关对象 剖面图 SQLAlchemy 1.4/2.0教程 :
EXISTS forms:has()/any() - helpers to generate EXISTS clauses using
relationship()
公共关系运算符 -帮助程序根据
relationship()
引用特定对象实例
ORM加载程序选项
加载程序选项是传递给 Select.options()
方法,该方法同时影响列和面向关系的属性的加载。大多数装载机选项从 Load
等级制度。有关使用加载程序选项的完整概述,请参阅下面的链接部分。
参见
加载柱 -详细说明映射器和加载选项,这些选项会影响列和SQL表达式映射属性的加载方式
关系加载技术 -详细说明关系和加载选项如何影响
relationship()
已加载映射属性
ORM执行选项
执行选项是传递给“执行选项”方法的关键字参数,它发生在语句执行级别。主要的“执行选项”方法位于 Connection.execution_options()
. 在ORM中,执行选项也可以传递给 Session.execute()
使用 Session.execute.execution_options
参数。也许更简洁地说,大多数执行选项,包括那些特定于ORM的选项,都可以使用 Executable.execution_options()
方法,以便选项可以直接与语句关联,而不是单独配置。以下示例将使用此表单。
填充现有
这个 populate_existing
execution选项确保对于加载的所有行 Session
将完全刷新,删除对象中的任何现有数据(包括挂起的更改),并替换为从结果加载的数据。
示例用法如下:
>>> stmt = select(User).execution_options(populate_existing=True) sql>>> result = session.execute(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account ...
通常,ORM对象只加载一次,如果它们与后续结果行中的主键匹配,则该行不会应用于该对象。这既可以保留对象上挂起的、未刷新的更改,也可以避免刷新已存在的数据的开销和复杂性。这个 Session
假设一个高度隔离的事务的默认工作模型,并且如果数据预期在事务内部发生变化,那么这些用例将使用显式的步骤(如此方法)进行处理。
使用 populate_existing
,可以刷新与查询匹配的任何对象集,并且还允许控制关系加载器选项。例如,要在刷新实例的同时刷新相关的一组对象,请执行以下操作:
stmt = ( select(User). where(User.name.in_(names)). execution_options(populate_existing=True). options(selectinload(User.addresses) ) # will refresh all matching User objects as well as the related # Address objects users = session.execute(stmt).scalars().all()
另一个用例 populate_existing
支持各种属性加载功能,这些特性可以更改每个查询加载属性的方式。适用的选项包括:
这个
with_expression()
选项这个
PropComparator.and_()
方法,该方法可以修改加载程序策略加载的内容这个
contains_eager()
选项这个
with_loader_criteria()
选项
这个 populate_existing
执行选项等同于 Query.populate_existing()
方法在 1.x style ORM查询。
参见
我正在用会话加载数据,但没有看到我在其他地方所做的更改。 - in 常见问题
自动冲洗
此选项传递为 False
将导致 Session
不调用“自动刷新”步骤。相当于使用 Session.no_autoflush
要禁用自动刷新的上下文管理器:
>>> stmt = select(User).execution_options(autoflush=False) sql>>> session.execute(stmt) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account ...
此选项也适用于启用ORM的情况 Update
和 Delete
查询。
这个 autoflush
执行选项等同于 Query.autoflush()
方法在 1.x style ORM查询。
参见
单位产量
这个 yield_per
执行选项是一个整数值,它将导致 Result
一次只产生固定数量的行。它通常与结果分区方法一起使用,例如 Result.partitions()
,例如:
>>> stmt = select(User).execution_options(yield_per=10) sql>>> for partition in session.execute(stmt).partitions(10): ... for row in partition: ... print(row) SELECT user_account.id, user_account.name, user_account.fullname FROM user_account [...] () (User(id=1, name='spongebob', fullname='Spongebob Squarepants'),) ...
此方法的目的是在获取非常大的结果集(>10000行)时,对子集合中的结果进行批处理并部分生成结果,这样Python解释器就不需要声明非常大的内存区域,这既耗时又会导致内存使用过度。当使用适当的每次设置的收益率(例如大约1000)时,提取数十万行的性能通常会加倍,即使DBAPIS缓冲行(最多)。
什么时候? yield_per
被使用了 Connection.execution_options.stream_results
还为核心执行设置了选项,以便在后端支持流式处理/服务器端游标时使用它 1
这个 yield_per
执行选项 使用集合时与subqueryload紧急加载或joinedload紧急加载不兼容 . 它可能与selectinload eager loading兼容, 如果数据库驱动程序支持多个独立的游标 2 .
此外, yield_per
执行选项与 Result.unique()
由于此方法依赖于存储所有行的完整标识集,因此它必然会违背使用 yield_per
这是为了处理任意数量的行。
在 1.4.6 版更改: 对象读取ORM行时引发异常 Result
对象,该对象利用 Result.unique()
过滤的同时, yield_per
使用执行选项。
这个 yield_per
执行选项等同于 Query.yield_per()
方法在 1.x style ORM查询。
- 1
目前已知的
psycopg2
,mysqldb
和pymysql
. 其他后端将预缓冲所有行。原始数据库行的内存使用量远小于ORM映射对象的内存使用量,但在进行基准测试时仍应将其考虑在内。- 2
这个
psycopg2
和pysqlite
已知驱动程序可以工作,但MySQL和SQL Server ODBC驱动程序不工作。
参见
使用任意WHERE子句更新/删除
这个 Session.execute()
方法,除了处理启用的ORM Select
对象,也可以容纳启用了ORM的 Update
和 Delete
对象,它更新或删除任意数量的数据库行,同时还能够同步中本地存在的匹配对象的状态 Session
. 参见章节 使用任意WHERE子句更新和删除 关于这个功能的背景。