SqlAlchemy 2.0 中文文档(二十一)(3)https://developer.aliyun.com/article/1560621
参数:
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 时,返回的查询在执行某些操作之前不会断言其状态,包括在调用filter()
时未应用 LIMIT/OFFSET,在调用get()
时不存在条件,以及在调用filter()
/order_by()
/group_by()
时不存在“from_statement()”。 此更宽松的模式由自定义查询子类使用,以指定通常用法模式之外的条件或其他修改器。
应注意确保使用模式是可行的。 例如,由from_statement()
应用的语句将覆盖filter()
或order_by()
设置的任何条件。
method enable_eagerloads(value: bool) → Self
控制是否渲染急切连接和子查询。
当设置为 False 时,返回的查询不会渲染急切连接,而不管joinedload()
,subqueryload()
选项或映射级别的lazy='joined'
/lazy='subquery'
配置。
主要用于将查询的语句嵌套到子查询或其他可选择项中,或者使用Query.yield_per()
时。
method except_(*q: Query) → Self
对一个或多个查询产生此查询的差集。
与Query.union()
的工作方式相同。 有关用法示例,请参见该方法。
另请参阅
Select.except_()
- v2 等效方法。
method except_all(*q: Query) → Self
对一个或多个查询产生此查询的全集。
与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 版本中新增:- 在 Query.execution_options()
中添加了 ORM 选项
使用 2.0 风格 查询时,也可以在每次执行时指定执行选项,通过 Session.execution_options
参数。
警告
不应在单个 ORM 语句执行的级别使用 Connection.execution_options.stream_results
参数,因为 Session
不会跟踪来自单个会话中的不同模式转换映射的对象。对于在单个 Session
范围内的多个模式转换映射,请参阅水平分片。
另请参阅
使用服务器端游标(即流式结果)
Query.get_execution_options()
Select.execution_options()
- v2 相当的方法。
method exists() → Exists
一个方便的方法,将查询转换为 EXISTS 子查询的形式 EXISTS (SELECT 1 FROM … WHERE …)。
例如:
q = session.query(User).filter(User.name == 'fred') session.query(q.exists())
生成类似于以下 SQL:
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 表达式。要根据 EXISTS 在 WHERE 中作为 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 中应用了一个限制为一的限制,因此只在服务器端生成一个主实体行(请注意,如果存在联接加载的集合,则可能由多个结果行组成)。
调用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()
应用加载选项,并且如果对象尚未在本地存在,则将使用该选项。
参数:
ident –
代表主键的标量、元组或字典。对于复合(例如多列)主键,应传递元组或字典。
对于单列主键,标量调用形式通常是最方便的。如果一行的主键是值“5”,则调用如下所示:
my_object = query.get(5)
元组形式包含主键值,通常按照它们对应于映射的Table
对象的主键列的顺序,或者如果使用了Mapper.primary_key
配置参数,则按照该参数的顺序使用。例如,如果一行的主键由整数数字“5, 10”表示,调用将如下所示:
my_object = query.get((5, 10))
字典形式应将映射属性名称作为每个主键元素对应的键。如果映射类具有 id
、version_id
作为存储对象主键值的属性,则调用如下:
my_object = query.get({"id": 5, "version_id": 10})
版本 1.3 中的新功能:Query.get()
方法现在可选地接受属性名称到值的字典,以指示主键标识符。
返回:
对象实例,或 None
。
method get_children(*, omit_attrs: Tuple[str, ...] = (), **kw: Any) → Iterable[HasTraverseInternals]
继承自 HasTraverseInternals.get_children()
方法的 HasTraverseInternals
返回此 HasTraverseInternals
的直接子级 HasTraverseInternals
元素。
这用于访问遍历。
**kw 可能包含改变返回的集合的标志,例如为了减少更大的遍历而返回子集,或者从不同上下文(例如模式级别集合而不是从子句级别)返回子项。
method get_execution_options() → _ImmutableExecuteOptions
获取在执行期间生效的非 SQL 选项。
版本 1.3 中的新功能。
另请参阅
Query.execution_options()
Select.get_execution_options()
- v2 可比较方法。
attribute get_label_style
检索当前的标签样式。
版本 1.4 中的新功能。
另请参阅
Select.get_label_style()
- v2 等效方法。
method group_by(_Query__first: Literal[None, False, _NoArg.NO_ARG] | _ColumnExpressionOrStrLabelArgument[Any] = _NoArg.NO_ARG, *clauses: _ColumnExpressionOrStrLabelArgument[Any]) → Self
对查询应用一个或多个 GROUP BY 准则,并返回新生成的 Query
。
所有现有的 GROUP BY 设置都可以通过传递 None
来抑制 - 这也会抑制映射器上配置的任何 GROUP BY。
另请参阅
这些部分描述了 GROUP BY 的 2.0 风格 调用,但同样适用于 Query
:
带有 GROUP BY / HAVING 的聚合函数 - 在 SQLAlchemy 统一教程 中
按标签排序或分组 - 在 SQLAlchemy 统一教程 中
Select.group_by()
- v2 等效方法。
method having(*having: _ColumnExpressionArgument[bool]) → Self
对查询应用 HAVING 准则,并返回新生成的 Query
。
Query.having()
与 Query.group_by()
结合使用。
HAVING 条件使得可以对像 COUNT、SUM、AVG、MAX 和 MIN 这样的聚合函数使用过滤器,例如:
q = session.query(User.id).\ join(User.addresses).\ group_by(User.id).\ having(func.count(Address.id) > 2)
另请参见
Select.having()
- v2 等效方法。
method instances(result_proxy: CursorResult[Any], context: QueryContext | None = None) → Any
在给定 CursorResult
和 QueryContext
的情况下返回 ORM 结果。
自版本 2.0 起已弃用:Query.instances()
方法已弃用,并将在以后的版本中删除。请改用 Select.from_statement() 方法或与 Session.execute() 结合使用的 aliased() 构造。
method intersect(*q: Query) → Self
对此查询与一个或多个查询进行 INTERSECT 操作。
与 Query.union()
的工作方式相同。查看该方法以获取使用示例。
另请参见
Select.intersect()
- v2 等效方法。
method intersect_all(*q: Query) → Self
对此查询与一个或多个查询进行 INTERSECT ALL 操作。
与 Query.union()
的工作方式相同。查看该方法以获取使用示例。
另请参见
Select.intersect_all()
- v2 等效方法。
attribute is_single_entity
指示此 Query
返回元组还是单个实体。
如果此查询为其结果列表中的每个实例返回单个实体,则返回 True,如果此查询为每个结果返回实体元组,则返回 False。
新版本 1.3.11 中新增。
另请参见
Query.only_return_tuples()
method join(target: _JoinTargetArgument, onclause: _OnClauseArgument | None = None, *, isouter: bool = False, full: bool = False) → Self
创建针对此 Query
对象的条件的 SQL JOIN,并以生成方式应用,返回新生成的 Query
。
简单关系连接
考虑两个类 User
和 Address
之间的映射,其中关系 User.addresses
表示与每个 User
关联的 Address
对象的集合。Query.join()
的最常见用法是沿着这个关系创建 JOIN,使用 User.addresses
属性作为指示器来指示如何发生这种情况:
q = session.query(User).join(User.addresses)
在上面的例子中,沿着 User.addresses
调用 Query.join()
将导致大致等同于以下 SQL:
SELECT user.id, user.name FROM user JOIN address ON user.id = address.user_id
在上面的例子中,我们将User.addresses
称为传递给 Query.join()
的“on clause”,也就是说,它指示了“JOIN”的“ON”部分应如何构建。
要构建一系列连接,可以使用多个Query.join()
调用。关系绑定的属性同时暗示连接的左侧和右侧:
q = session.query(User).\ join(User.orders).\ join(Order.items).\ join(Item.keywords)
注意
如上例所示,每次调用 join()方法的顺序很重要。例如,如果我们在连接链中指定User
、然后是Item
、然后是Order
,那么 Query 不会正确知道如何连接;在这种情况下,根据传递的参数,它可能会引发一个无法连接的错误,或者它可能会生成无效的 SQL,而数据库会引发一个错误。在正确的实践中,应以使得 JOIN 子句在 SQL 中呈现的方式调用Query.join()
方法,并且每次调用应该表示与之前内容的清晰关联。
连接到目标实体或可选择的
Query.join()
的第二种形式允许任何映射实体或核心可选择的构造作为目标。在这种用法中,Query.join()
将尝试沿着两个实体之间的自然外键关系创建一个 JOIN:
q = session.query(User).join(Address)
在上述调用形式中,Query.join()
被调用来自动为我们创建“on 子句”。如果两个实体之间没有外键,或者如果目标实体和左侧已存在的实体之间有多个外键链接,以至于创建连接需要更多信息,则此调用形式最终将引发错误。请注意,在指示对没有任何 ON 子句的目标的连接时,不会考虑 ORM 配置的关系。
连接到具有 ON 子句的目标
第三种调用形式允许显式传递目标实体以及 ON 子句。包含 SQL 表达式作为 ON 子句的示例如下所示:
q = session.query(User).join(Address, User.id==Address.user_id)
上述形式也可以使用一个与关系绑定的属性作为 ON 子句:
q = session.query(User).join(Address, User.addresses)
上述语法对于我们希望连接到特定目标实体的别名的情况可能很有用。如果我们想要两次连接到Address
,可以使用aliased()
函数设置两个别名:
a1 = aliased(Address) a2 = aliased(Address) q = session.query(User).\ join(a1, User.addresses).\ join(a2, User.addresses).\ filter(a1.email_address=='ed@foo.com').\ filter(a2.email_address=='ed@bar.com')
与关系绑定的调用形式还可以使用PropComparator.of_type()
方法指定目标实体;一个与上述相同的查询将是:
a1 = aliased(Address) a2 = aliased(Address) q = session.query(User).\ join(User.addresses.of_type(a1)).\ join(User.addresses.of_type(a2)).\ filter(a1.email_address == 'ed@foo.com').\ filter(a2.email_address == 'ed@bar.com')
扩充内置的 ON 子句
作为为现有关系提供完整自定义 ON 条件的替代方法,可以将PropComparator.and_()
函数应用于关系属性,以将其他条件合并到 ON 子句中;其他条件将与默认条件使用 AND 组合:
q = session.query(User).join( User.addresses.and_(Address.email_address != 'foo@bar.com') )
1.4 版本中新增。
加入表格和子查询
加入的目标也可以是任何表格或 SELECT 语句,它可以与目标实体相关联,也可以不相关联。使用适当的.subquery()
方法以将查询转换为子查询:
subq = session.query(Address).\ filter(Address.email_address == 'ed@foo.com').\ subquery() q = session.query(User).join( subq, User.id == subq.c.user_id )
通过使用aliased()
将子查询链接到实体,可以在特定关系和/或目标实体方面加入子查询:
subq = session.query(Address).\ filter(Address.email_address == 'ed@foo.com').\ subquery() address_subq = aliased(Address, subq) q = session.query(User).join( User.addresses.of_type(address_subq) )
控制加入来源
在当前Query
状态的左侧与我们想要加入的内容不一致的情况下,可以使用Query.select_from()
方法:
q = session.query(Address).select_from(User).\ join(User.addresses).\ filter(User.name == 'ed')
这将产生类似于以下的 SQL:
SELECT address.* FROM user JOIN address ON user.id=address.user_id WHERE user.name = :name_1
另请参阅
Select.join()
- v2 等效方法。
SqlAlchemy 2.0 中文文档(二十一)(5)https://developer.aliyun.com/article/1560624