传统查询 API
关于传统查询 API
本页包含了由 Python 生成的Query
构造的文档,多年来这是与 SQLAlchemy ORM 一起使用时的唯一 SQL 接口。从版本 2.0 开始,现在采用的是全新的工作方式,其中与 Core 相同的select()
构造对 ORM 同样有效,为构建查询提供了一致的接口。
对于在 SQLAlchemy 2.0 API 之前构建的任何应用程序,Query
API 通常表示应用程序中绝大多数数据库访问代码,并且大部分Query
API 不会从 SQLAlchemy 中删除。在执行Query
对象时,Query
对象在幕后现在会将自己转换为 2.0 样式的select()
对象,因此现在它只是一个非常薄的适配器 API。
要了解如何将基于Query
的应用程序迁移到 2.0 样式,请参阅 2.0 迁移 - ORM 用法。
要了解如何以 2.0 样式编写 ORM 对象的 SQL,请从 SQLAlchemy 统一教程开始。2.0 样式查询的其他参考资料请参阅 ORM 查询指南。
查询对象
Query
是根据给定的Session
产生的,使用Session.query()
方法:
q = session.query(SomeMappedClass)
以下是Query
对象的完整接口。
对象名称 | 描述 |
查询 | ORM 级别的 SQL 构造对象。 |
class sqlalchemy.orm.Query
ORM 级别的 SQL 构造对象。
传统特性
ORM Query
对象是 SQLAlchemy 2.0 的传统构造。请参阅传统查询 API 顶部的注释,其中包括迁移文档的链接。
查询
对象通常最初是使用 Session.query()
方法生成的,Session
的情况比较少是直接实例化 Query
并使用 Query.with_session()
方法与 Session
关联。
成员
init(), add_column(), add_columns(), add_entity(), all(), apply_labels(), as_scalar(), autoflush(), column_descriptions, correlate(), count(), cte(), delete(), distinct(), enable_assertions(), enable_eagerloads(), except_(), except_all(), execution_options(), exists(), filter(), filter_by(), first(), from_statement(), get(), get_children(), get_execution_options(), get_label_style, group_by(), having(), instances(), intersect(), intersect_all(), is_single_entity, join(), label(), lazy_loaded_from, limit(), merge_result(), offset(), one(), one_or_none(), only_return_tuples(), options(), order_by(), outerjoin(), params(), populate_existing(), prefix_with(), reset_joinpoint(), scalar(), scalar_subquery(), select_from(), selectable, set_label_style(), slice(), statement, subquery(), suffix_with(), tuples(), union(), union_all(), update(), value(), values(), where(), whereclause, with_entities(), with_for_update(), with_hint(), with_labels(), with_parent(), with_session(), with_statement_hint(), with_transformation(), yield_per()
类签名
类sqlalchemy.orm.Query
(sqlalchemy.sql.expression._SelectFromElements
,sqlalchemy.sql.annotation.SupportsCloneAnnotations
,sqlalchemy.sql.expression.HasPrefixes
,sqlalchemy.sql.expression.HasSuffixes
,sqlalchemy.sql.expression.HasHints
,sqlalchemy.event.registry.EventTarget
,sqlalchemy.log.Identified
,sqlalchemy.sql.expression.Generative
,sqlalchemy.sql.expression.Executable
,typing.Generic
)
method __init__(entities: _ColumnsClauseArgument[Any] | Sequence[_ColumnsClauseArgument[Any]], session: Session | None = None)
直接构造一个Query
。
例如:
q = Query([User, Address], session=some_session)
以上等价于:
q = some_session.query(User, Address)
参数:
entities
– 一个实体和/或 SQL 表达式的序列。session
– 与Query
将关联的Session
。可选;也可以通过Query.with_session()
方法将Query
与Session
关联。
另请参见
Session.query()
Query.with_session()
method add_column(column: _ColumnExpressionArgument[Any]) → Query[Any]
将列表达式添加到要返回的结果列列表中。
自版本 1.4 起已弃用:Query.add_column()
已弃用,并将在将来的版本中删除。请使用 Query.add_columns()
method add_columns(*column: _ColumnExpressionArgument[Any]) → Query[Any]
将一个或多个列表达式添加到要返回的结果列列表中。
另请参见
Select.add_columns()
- v2 可比较的方法。
method add_entity(entity: _EntityType[Any], alias: Alias | Subquery | None = None) → Query[Any]
将映射实体添加到要返回的结果列列表中。
另请参见
Select.add_columns()
- v2 可比较的方法。
method all() → List[_T]
将由此Query
表示的结果返回为列表。
这将导致底层 SQL 语句的执行。
警告
当要求 Query
对象返回由完整的 ORM 映射实体组成的序列或迭代器时,将根据主键对条目进行去重。有关更多详情,请参阅 FAQ。
另请参阅
我的查询返回的对象数量与 query.count() 告诉我的数量不一致 - 为什么?
另请参阅
Result.all()
- v2 可比较方法。
Result.scalars()
- v2 可比较方法。
method apply_labels() → Self
自版本 2.0 弃用:Query.with_labels()
和 Query.apply_labels()
方法被视为 SQLAlchemy 1.x 系列的遗留构造,在 2.0 中成为遗留构造。请改用 set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL)
。 (有关 SQLAlchemy 2.0 的背景,请参阅:SQLAlchemy 2.0 - Major Migration Guide)
method as_scalar() → ScalarSelect[Any]
返回由此 Query
表示的完整 SELECT 语句,转换为标量子查询。
自版本 1.4 弃用:Query.as_scalar()
方法已弃用,并将在将来的版本中删除。请参考 Query.scalar_subquery()
。
method autoflush(setting: bool) → Self
返回具有特定“autoflush”设置的查询。
自 SQLAlchemy 1.4 起,Query.autoflush()
方法等效于在 ORM 级别使用 autoflush
执行选项。有关此选项的更多背景,请参阅 Autoflush 部分。
attribute column_descriptions
返回有关此 Query
将返回的列的元数据。
格式是一个字典列表:
user_alias = aliased(User, name='user2') q = sess.query(User, User.id, user_alias) # this expression: q.column_descriptions # would return: [ { 'name':'User', 'type':User, 'aliased':False, 'expr':User, 'entity': User }, { 'name':'id', 'type':Integer(), 'aliased':False, 'expr':User.id, 'entity': User }, { 'name':'user2', 'type':User, 'aliased':True, 'expr':user_alias, 'entity': user_alias } ]
另请参阅
此 API 也可使用 2.0 风格 查询,文档位于:
- 检查来自启用 ORM 的 SELECT 和 DML 语句的实体和列
Select.column_descriptions
method correlate(*fromclauses: Literal[None, False] | FromClauseRole | Type[Any] | Inspectable[_HasClauseElement[Any]] | _HasClauseElement[Any]) → Self
返回一个 Query
构造,将给定的 FROM 子句与封闭的 Query
或 select()
关联起来。
此处的方法接受映射类、aliased()
构造和 Mapper
构造作为参数,这些参数会被解析为表达式构造,以及适当的表达式构造。
最终,相关参数将被强制转换为表达式构造,然后传递给 Select.correlate()
。
在这种情况下,相关参数会生效,例如在使用 Query.from_self()
时,或者在将由Query.subquery()
返回的子查询嵌入到另一个select()
构造中时。
另请参阅
Select.correlate()
- v2 等效方法。
method count() → int
返回此Query
形成的 SQL 将返回的行数计数。
这将生成以下查询的 SQL 语句:
SELECT count(1) AS count_1 FROM ( SELECT <rest of query follows...> ) AS anon_1
上述 SQL 返回一个单行,即 count 函数的聚合值;然后Query.count()
方法返回该单个整数值。
警告
需要注意的是,count() 返回的值并不等同于此 Query 通过 .all() 等方法返回的 ORM 对象数。当 Query
对象被要求返回完整实体时,将根据主键对条目进行重复消除,这意味着如果相同的主键值在结果中出现超过一次,则只会存在一个该主键的对象。这不适用于针对单个列的查询。
另请参阅
我的查询的返回对象数与 query.count() 告诉我的不一样 - 为什么?
对于对特定列进行精细控制的计数,跳过子查询的使用或以其他方式控制 FROM 子句,或使用其他聚合函数,可以结合使用expression.func
表达式和 Session.query()
,例如:
from sqlalchemy import func # count User records, without # using a subquery. session.query(func.count(User.id)) # return count of user "id" grouped # by "name" session.query(func.count(User.id)).\ group_by(User.name) from sqlalchemy import distinct # count distinct "name" values session.query(func.count(distinct(User.name)))
另请参阅
2.0 迁移 - ORM 用法
method cte(name: str | None = None, recursive: bool = False, nesting: bool = False) → CTE
返回由此Query
表示的完整 SELECT 语句,表示为公共表达式(CTE)。
参数和用法与 SelectBase.cte()
方法相同;有关更多详细信息,请参阅该方法。
这里是 PostgreSQL WITH RECURSIVE 示例。请注意,在此示例中,included_parts
cte 和其 incl_alias
别名是核心可选择的,这意味着可以通过 .c.
属性访问列。parts_alias
对象是 Part
实体的 aliased()
实例,因此可以直接访问列映射属性:
from sqlalchemy.orm import aliased class Part(Base): __tablename__ = 'part' part = Column(String, primary_key=True) sub_part = Column(String, primary_key=True) quantity = Column(Integer) included_parts = session.query( Part.sub_part, Part.part, Part.quantity).\ filter(Part.part=="our part").\ cte(name="included_parts", recursive=True) incl_alias = aliased(included_parts, name="pr") parts_alias = aliased(Part, name="p") included_parts = included_parts.union_all( session.query( parts_alias.sub_part, parts_alias.part, parts_alias.quantity).\ filter(parts_alias.part==incl_alias.c.sub_part) ) q = session.query( included_parts.c.sub_part, func.sum(included_parts.c.quantity). label('total_quantity') ).\ group_by(included_parts.c.sub_part)
请参阅
Select.cte()
- v2 等效方法。
method delete(synchronize_session: SynchronizeSessionArgument = 'auto') → int
使用任意 WHERE 子句执行 DELETE。
从数据库中删除与此查询匹配的行。
例如:
sess.query(User).filter(User.age == 25).\ delete(synchronize_session=False) sess.query(User).filter(User.age == 25).\ delete(synchronize_session='evaluate')
警告
请参阅 ORM-Enabled INSERT、UPDATE 和 DELETE 语句 章节以了解重要的注意事项和警告,包括在使用映射器继承配置时批量 UPDATE 和 DELETE 的限制。
参数:
synchronize_session – 选择在会话中更新对象属性的策略。请参阅 ORM-Enabled INSERT、UPDATE 和 DELETE 语句 章节讨论这些策略。
返回:
数据库的“行计数”功能返回的匹配行数。
请参阅
ORM-Enabled INSERT、UPDATE 和 DELETE 语句
method distinct(*expr: _ColumnExpressionArgument[Any]) → Self
对查询应用 DISTINCT
并返回新生成的 Query
。
注意
ORM 级别的 distinct()
调用包含逻辑,将自动将查询的 ORDER BY 中的列添加到 SELECT 语句的列子句中,以满足数据库后端的常见需求,即在使用 DISTINCT 时,ORDER BY 列应作为 SELECT 列的一部分。然而,这些列 不会 添加到实际由 Query
获取的列列表中,因此不会影响结果。然而,在使用 Query.statement
访问器时,这些列会通过。
自版本 2.0 起已弃用:此逻辑已弃用,将在 SQLAlchemy 2.0 中删除。请参阅 使用 DISTINCT 与其他列,但仅选择实体 了解 2.0 中此用例的描述。
请参阅
Select.distinct()
- v2 等效方法。
参数:
*expr –
可选的列表达式。当存在时,PostgreSQL 方言将呈现 DISTINCT ON ()
结构。
自 1.4 版本起已弃用:在其他方言中使用*expr 已弃用,并将在将来的版本中引发CompileError
。
method enable_assertions(value: bool) → Self
控制是否生成断言。
当设置为 False 时,返回的 Query 在某些操作之前不会断言其状态,包括调用 filter() 时未应用 LIMIT/OFFSET,调用 get() 时不存在条件,以及调用 filter()/order_by()/group_by() 等时不存在“from_statement()”。此更宽松的模式由自定义的 Query 子类使用,以指定标准或其他修改器在通常的使用模式之外。
应注意确保使用模式是可行的。例如,由 from_statement()应用的语句将覆盖由 filter()或 order_by()设置的任何条件。
method enable_eagerloads(value: bool) → Self
控制是否呈现急切连接和子查询。
当设置为 False 时,返回的 Query 将不会渲染急切连接,无论 joinedload()
、subqueryload()
选项或映射器级别的 lazy='joined'
/lazy='subquery'
配置如何。
当将 Query 的语句嵌套到子查询或其他可选择项中时,或者当使用Query.yield_per()
时主要用于。
method except_(*q: Query) → Self
生成此 Query 对一项或多项查询的 EXCEPT。
与Query.union()
的工作方式相同。请参阅该方法以获取用法示例。
另请参阅
Select.except_()
- v2 等效方法。
method except_all(*q: Query) → Self
生成此 Query 对一项或多项查询的 EXCEPT ALL。
与Query.union()
的工作方式相同。请参阅该方法以获取用法示例。
另请参阅
Select.except_all()
- v2 等效方法。
method execution_options(**kwargs: Any) → Self
设置在执行期间生效的非 SQL 选项。
此处允许的选项包括所有被Connection.execution_options()
接受的选项,以及一系列 ORM 特定选项:
populate_existing=True
- 等效于使用Query.populate_existing()
autoflush=True|False
- 等效于使用Query.autoflush()
yield_per=
- 等效于使用Query.yield_per()
注意,如果使用了Query.yield_per()
方法或执行选项,则stream_results
执行选项会自动启用。
版本 1.4 中的新功能:- 添加了 ORM 选项到Query.execution_options()
在使用 2.0 风格查询时,执行选项也可以在每次执行时指定,通过Session.execution_options
参数。
警告
Connection.execution_options.stream_results
参数不应在单个 ORM 语句执行的级别使用,因为Session
不会跟踪来自不同模式转换映射的对象在单个会话中。对于单个Session
范围内的多个模式转换映射,请参见水平分片。
另请参阅
使用服务器端游标(又名流式结果)
Query.get_execution_options()
Select.execution_options()
- v2 等效方法。
method exists() → Exists
一个方便的方法,将查询转换为形式为 EXISTS(SELECT 1 FROM … WHERE …)的 EXISTS 子查询。
例如:
q = session.query(User).filter(User.name == 'fred') session.query(q.exists())
生成类似于:
SELECT EXISTS ( SELECT 1 FROM users WHERE users.name = :name_1 ) AS anon_1
EXISTS 构造通常用于 WHERE 子句中:
session.query(User.id).filter(q.exists()).scalar()
请注意,某些数据库(如 SQL Server)不允许在 SELECT 的列子句中存在 EXISTS 表达式。要基于存在性选择简单的布尔值作为 WHERE,使用literal()
:
from sqlalchemy import literal session.query(literal(True)).filter(q.exists()).scalar()
另请参阅
Select.exists()
- v2 可比较的方法。
method filter(*criterion: _ColumnExpressionArgument[bool]) → Self
将给定的过滤条件应用于此Query
的副本,使用 SQL 表达式。
例如:
session.query(MyClass).filter(MyClass.name == 'some name')
多个条件可以以逗号分隔的方式指定;效果是它们将使用and_()
函数连接在一起:
session.query(MyClass).\ filter(MyClass.name == 'some name', MyClass.id > 5)
条件是适用于 select 的 WHERE 子句的任何 SQL 表达式对象。字符串表达式通过text()
构造被强制转换为 SQL 表达式构造。
另请参阅
Query.filter_by()
- 根据关键字表达式进行过滤。
Select.where()
- v2 等效方法。
method filter_by(**kwargs: Any) → Self
将给定的过滤条件应用于此Query
的副本,使用关键字表达式。
例如:
session.query(MyClass).filter_by(name = 'some name')
可以指定多个条件,以逗号分隔;其效果是它们将使用and_()
函数连接在一起:
session.query(MyClass).\ filter_by(name = 'some name', id = 5)
关键字表达式是从查询的主要实体或最后一个曾被调用过Query.join()
的目标实体中提取的。
另请参阅
Query.filter()
- 根据 SQL 表达式进行过滤。
Select.filter_by()
- v2 可比较的方法。
method first() → _T | None
返回此Query
的第一个结果,如果结果不包含任何行,则返回 None。
first()
在生成的 SQL 中应用了一个限制为 1,因此仅在服务器端生成一个主要实体行(请注意,如果存在联接加载的集合,则可能由多个结果行组成)。
调用Query.first()
会导致基础查询的执行。
另请参阅
Query.one()
Query.one_or_none()
Result.first()
- v2 可比较的方法。
Result.scalars()
- v2 可比较的方法。
method from_statement(statement: ExecutableReturnsRows) → Self
执行给定的 SELECT 语句并返回结果。
此方法绕过所有内部语句编译,并且语句在不修改的情况下执行。
该语句通常是一个text()
或select()
结构,应返回与此Query
所代表的实体类相对应的列集。
另请参阅
Select.from_statement()
- v2 可比较的方法。
method get(ident: _PKIdentityArgument) → Any | None
根据给定的主键标识符返回一个实例,如果找不到则返回None
。
自版本 2.0 起已弃用:Query.get()
方法被认为是 SQLAlchemy 1.x 系列的遗留部分,并且在 2.0 中成为遗留构造。该方法现在可用作 Session.get()
(关于 SQLAlchemy 2.0 的背景信息,请参阅:SQLAlchemy 2.0 - 主要迁移指南)
例如:
my_user = session.query(User).get(5) some_object = session.query(VersionedFoo).get((5, 10)) some_object = session.query(VersionedFoo).get( {"id": 5, "version_id": 10})
Query.get()
特殊之处在于它提供对所属 Session
的标识映射的直接访问。如果给定的主键标识符存在于本地标识映射中,则对象将直接从此集合返回,而不会发出任何 SQL,除非对象已被标记为完全过期。如果不存在,则执行 SELECT 来定位对象。
Query.get()
会检查对象是否存在于标识映射中并标记为过期 - 会发出一个 SELECT 来刷新对象并确保行仍然存在。如果不存在,则会引发 ObjectDeletedError
。
Query.get()
仅用于返回单个映射实例,而不是多个实例或单个列构造,并且严格限于单个主键值。源 Query
必须以这种方式构造,即针对单个映射实体,没有额外的过滤条件。可以通过 Query.options()
应用加载选项,如果对象尚未在本地存在,则将使用该选项。
SqlAlchemy 2.0 中文文档(二十一)(2)https://developer.aliyun.com/article/1560617