SqlAlchemy 2.0 中文文档(二十一)(4)

简介: SqlAlchemy 2.0 中文文档(二十一)

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))

字典形式应将映射属性名称作为每个主键元素对应的键。如果映射类具有 idversion_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

在给定 CursorResultQueryContext 的情况下返回 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

简单关系连接

考虑两个类 UserAddress 之间的映射,其中关系 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

相关文章
|
3天前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(二十九)(3)
SqlAlchemy 2.0 中文文档(二十九)
16 4
|
3天前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(二十九)(2)
SqlAlchemy 2.0 中文文档(二十九)
20 7
|
3天前
|
SQL 存储 关系型数据库
SqlAlchemy 2.0 中文文档(二十九)(1)
SqlAlchemy 2.0 中文文档(二十九)
16 4
|
3天前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(二十九)(4)
SqlAlchemy 2.0 中文文档(二十九)
16 4
|
3天前
|
SQL 前端开发 关系型数据库
SqlAlchemy 2.0 中文文档(二十七)(2)
SqlAlchemy 2.0 中文文档(二十七)
14 2
|
3天前
|
SQL 缓存 前端开发
SqlAlchemy 2.0 中文文档(二十七)(5)
SqlAlchemy 2.0 中文文档(二十七)
10 2
|
3天前
|
SQL 测试技术 API
SqlAlchemy 2.0 中文文档(二十)(4)
SqlAlchemy 2.0 中文文档(二十)
10 1
|
3天前
|
SQL 缓存 API
SqlAlchemy 2.0 中文文档(二十)(5)
SqlAlchemy 2.0 中文文档(二十)
9 1
|
3天前
|
SQL 存储 测试技术
SqlAlchemy 2.0 中文文档(二十)(3)
SqlAlchemy 2.0 中文文档(二十)
10 1
|
3天前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(二十九)(5)
SqlAlchemy 2.0 中文文档(二十九)
11 1