SqlAlchemy 2.0 中文文档(四十四)(5)https://developer.aliyun.com/article/1563072
参数:
num – 每次重新填充缓冲区时获取的行数。如果设置为小于 1 的值,则获取下一个缓冲区的所有行。
另请参阅
使用服务器端游标(即流式结果) - 描述了 Result.yield_per() 的核心行为
使用 Yield Per 获取大型结果集 - 在 ORM 查询指南 中
class sqlalchemy.engine.ScalarResult
一个 Result 的包装器,返回标量值而不是 Row 值。
ScalarResult 对象是通过调用 Result.scalars() 方法获取的。
ScalarResult 的一个特殊限制是它没有 fetchone() 方法;因为 fetchone() 的语义是 None 值表示没有更多结果,这与 ScalarResult 不兼容,因为无法区分 None 作为行值与 None 作为指示符的情况。使用 next(result) 逐个接收值。
成员
all(), close(), closed, fetchall(), fetchmany(), first(), one(), one_or_none(), partitions(), unique(), yield_per()
类签名
类 sqlalchemy.engine.ScalarResult (sqlalchemy.engine.FilterResult)
method all() → Sequence[_R]
返回所有标量值的序列。
等同于Result.all(),但返回的是标量值,而不是Row对象。
method close() → None
继承自 FilterResult.close() 方法的 FilterResult
关闭此FilterResult。
在 1.4.43 版本中新增。
attribute closed
继承自 FilterResult.closed 属性的 FilterResult
如果底层的Result报告已关闭,则返回True。
在 1.4.43 版本中新增。
method fetchall() → Sequence[_R]
ScalarResult.all()方法的同义词。
method fetchmany(size: int | None = None) → Sequence[_R]
获取多个对象。
等同于Result.fetchmany(),但返回的是标量值,而不是Row对象。
method first() → _R | None
获取第一个对象,如果没有对象存在则返回None。
等同于Result.first(),但返回的是标量值,而不是Row对象。
method one() → _R
返回一个对象,或者引发异常。
等同于Result.one(),但返回的是标量值,而不是Row对象。
method one_or_none() → _R | None
返回最多一个对象,或者引发异常。
等同于Result.one_or_none(),但返回的是标量值,而不是Row对象。
method partitions(size: int | None = None) → Iterator[Sequence[_R]]
迭代给定大小的子列表元素。
等同于Result.partitions(),但返回的是标量值,而不是Row对象。
method unique(strategy: Callable[[Any], Any] | None = None) → Self
对由此ScalarResult返回的对象应用唯一过滤。
有关使用详细信息,请参阅Result.unique()。
method yield_per(num: int) → Self
继承自 FilterResult.yield_per() 方法的 FilterResult
配置行获取策略,一次获取num行。
FilterResult.yield_per()方法是对Result.yield_per()方法的传递。请参阅该方法的文档以获取使用说明。
版本 1.4.40 中的新增内容:- 添加了FilterResult.yield_per(),以便在所有结果集实现中都可用。
另请参阅
使用服务器端游标(即流式结果) - 描述了Result.yield_per()的核心行为。
使用每次产生的大型结果集 - 在 ORM 查询指南中。
class sqlalchemy.engine.MappingResult
一个Result的包装器,返回的是字典值而不是Row的值。
调用Result.mappings()方法获取MappingResult对象。
成员
all(), close(), closed, columns(), fetchall(), fetchmany(), fetchone(), first(), keys(), one(), one_or_none(), partitions(), unique(), yield_per()
类签名
类sqlalchemy.engine.MappingResult (sqlalchemy.engine._WithKeys, sqlalchemy.engine.FilterResult)
method all() → Sequence[RowMapping]
在序列中返回所有标量值。
与Result.all()相当,只是返回的是RowMapping值,而不是Row对象。
method close() → None
继承自 FilterResult.close() 方法的 FilterResult。
关闭此FilterResult。
版本 1.4.43 中的新增内容。
attribute closed
继承自 FilterResult.closed 属性的 FilterResult
如果底层的Result报告已关闭,则返回True。
1.4.43 版本中的新功能。
method columns(*col_expressions: _KeyIndexType) → Self
确定应在每行中返回的列。
method fetchall() → Sequence[RowMapping]
MappingResult.all()方法的同义词。
method fetchmany(size: int | None = None) → Sequence[RowMapping]
检索多个对象。
等同于Result.fetchmany(),除了返回RowMapping值,而不是Row对象。
method fetchone() → RowMapping | None
检索一个对象。
等同于Result.fetchone(),除了返回RowMapping值,而不是Row对象。
method first() → RowMapping | None
检索第一个对象或如果没有对象则返回None。
等同于Result.first(),除了返回RowMapping值,而不是Row对象。
method keys() → RMKeyView
继承自 sqlalchemy.engine._WithKeys.keys 方法的 sqlalchemy.engine._WithKeys
返回一个可迭代视图,该视图产生每个Row将表示的字符串键。
键可以表示核心语句返回的列的标签或 orm 执行返回的 orm 类的名称。
视图还可以使用 Python in 运算符进行键包含性测试,该运算符将测试视图中表示的字符串键以及列对象等替代键。
在 1.4 版本中更改:返回一个键视图对象而不是一个简单的列表。
method one() → RowMapping
返回一个对象或引发异常。
等同于Result.one(),除了返回RowMapping值,而不是Row对象。
method one_or_none() → RowMapping | None
返回至多一个对象或引发异常。
等同于Result.one_or_none(),除了返回RowMapping值,而不是Row对象。
method partitions(size: int | None = None) → Iterator[Sequence[RowMapping]]
迭代给定大小的元素子列表。
与 Result.partitions() 相当,但返回的是 RowMapping 值,而不是 Row 对象。
method unique(strategy: Callable[[Any], Any] | None = None) → Self
将唯一过滤应用于此 MappingResult 返回的对象。
请参阅 Result.unique() 获取使用详情。
method yield_per(num: int) → Self
继承自 FilterResult.yield_per() 方法的 FilterResult
将行获取策略配置为一次获取 num 行。
FilterResult.yield_per() 方法是对 Result.yield_per() 方法的简单封装。查看该方法的文档以获取使用说明。
版本 1.4.40 中新增:- 添加了 FilterResult.yield_per() 以便在所有结果集实现上都可用该方法
另请参阅
使用服务器端游标(即流式结果) - 描述 Result.yield_per() 的核心行为
使用 Yield Per 获取大型结果集 - 在 ORM 查询指南 中
class sqlalchemy.engine.Row
表示单个结果行。
Row 对象表示数据库结果的一行。在 SQLAlchemy 1.x 系列中,它通常与 CursorResult 对象关联,但自 SQLAlchemy 1.4 起也被 ORM 用于类似元组的结果。
Row 对象致力于尽可能像 Python 命名元组一样行事。要获取行上的映射(即字典)行为,例如检查键的包含,请参阅 Row._mapping 属性。
另请参阅
使用 SELECT 语句 - 包括从 SELECT 语句中选择行的示例。
从 1.4 版本开始更改:将 RowProxy 重命名为 Row。 Row 不再是“代理”对象,因为它包含其中的最终数据形式,现在大部分像命名元组一样操作。类似映射的功能移到了 Row._mapping 属性。有关此更改的背景,请参阅 RowProxy 不再是“代理”;现在称为 Row 并像增强的命名元组一样运行。
成员
_asdict(), _fields, _mapping, _t, _tuple(), count, index, t, tuple()
类签名
类 sqlalchemy.engine.Row (sqlalchemy.engine._py_row.BaseRow, collections.abc.Sequence, typing.Generic)
method _asdict() → Dict[str, Any]
返回一个新字典,将字段名映射到其相应的值。
此方法类似于 Python 命名元组的 ._asdict() 方法,并通过将 dict() 构造函数应用于 Row._mapping 属性来工作。
自 1.4 版本新增。
另请参阅
Row._mapping
attribute _fields
返回此 Row 所代表的字符串键的元组。
键可以表示核心语句返回的列的标签或 orm 执行返回的 orm 类的名称。
此属性类似于 Python 命名元组 ._fields 属性。
自 1.4 版本新增。
另请参阅
Row._mapping
attribute _mapping
返回此 Row 的 RowMapping。
此对象为行中包含的数据提供了一致的 Python 映射(即字典)接口。 单独的 Row 行为类似命名元组。
另请参阅
Row._fields
自 1.4 版本新增。
attribute _t
Row._tuple() 的同义词。
从 2.0.19 版本新增:Row._t 属性取代了先前的 Row.t 属性,现在以下划线开头以避免与列名发生冲突,与 Row 上的其他命名元组方法一样。
另请参阅
Result.t
method _tuple() → _TP
返回此 Row 的‘元组’形式。
在运行时,此方法返回“self”;Row 对象已经是一个命名元组。然而,在类型级别上,如果此 Row 被类型化,那么“元组”返回类型将是一个 PEP 484 的 Tuple 数据类型,其中包含有关各个元素的类型信息,支持类型化的解包和属性访问。
自 2.0.19 版新增:Row._tuple() 方法取代了以前的 Row.tuple() 方法,现在该方法已经被下划线标记,以避免与列名发生名称冲突,方式与其他命名元组方法在 Row 上一样。
另请参见
Row._t - 简写属性表示法
Result.tuples()
attribute count
attribute index
attribute t
Row._tuple() 的同义词。
自 2.0.19 版起不推荐使用:Row.t 属性已被废弃,建议使用 Row._t;所有 Row 方法和库级属性都应以下划线开头,以避免名称冲突。请使用 Row._t。
自 2.0 版本新增。
method tuple() → _TP
返回此 Row 的‘元组’形式。
自 2.0.19 版起不推荐使用:Row.tuple() 方法已被废弃,建议使用 Row._tuple();所有 Row 方法和库级属性都应以下划线开头,以避免名称冲突。请使用 Row._tuple()。
自 2.0 版本新增。
class sqlalchemy.engine.RowMapping
将列名和对象映射到 Row 值的映射。
RowMapping 可以通过 Row 的 Row._mapping 属性获得,也可以通过 Result.mappings() 方法返回的 MappingResult 对象提供的可迭代接口获得。
RowMapping 提供了对行内容的 Python 映射(即字典)访问。这包括支持测试特定键(字符串列名或对象)的包含性,以及对键、值和项的迭代:
for row in result: if 'a' in row._mapping: print("Column 'a': %s" % row._mapping['a']) print("Column b: %s" % row._mapping[table.c.b])
新版本 1.4 中:RowMapping 对象取代了以前由数据库结果行提供的类似映射的访问,现在它主要表现得像一个命名元组。
成员
items(), keys(), values()
类签名
类sqlalchemy.engine.RowMapping (sqlalchemy.engine._py_row.BaseRow, collections.abc.Mapping, typing.Generic)
method items() → ROMappingItemsView
返回底层Row中元素的键/值元组视图。
method keys() → RMKeyView
返回底层Row中表示的字符串列名的‘keys’视图。
method values() → ROMappingKeysValuesView
返回底层Row中表示的值的视图。
class sqlalchemy.engine.TupleResult
一个Result,其类型为返回普通 Python 元组而不是行。
由于Row在任何方面都像一个元组,因��这个类只是一个类型类,运行时仍然使用常规Result。
类签名
类sqlalchemy.engine.TupleResult(sqlalchemy.engine.FilterResult, sqlalchemy.util.langhelpers.TypingOnly)
基本用法
从 Engine Configuration 中回想,Engine 是通过create_engine()调用创建的:
engine = create_engine("mysql+mysqldb://scott:tiger@localhost/test")
create_engine() 的典型用法是针对特定数据库 URL 每次一次,全局保存在单个应用程序进程的生命周期中。一个Engine 代表进程上的许多个体 DBAPI 连接,并且旨在以并发方式调用。Engine 不等同于 DBAPI connect() 函数,后者仅表示一个连接资源 - 当在应用程序的模块级别创建一次时,Engine 在效率上最高,而不是每个对象或每个函数调用。
Engine 最基本的功能是提供对 Connection 的访问,然后可以调用 SQL 语句。向数据库发出文本语句如下所示:
from sqlalchemy import text with engine.connect() as connection: result = connection.execute(text("select username from users")) for row in result: print("username:", row.username)
在上述中,Engine.connect() 方法返回一个 Connection 对象,通过在 Python 上下文管理器中使用它(例如 with: 语句),Connection.close() 方法会在块结束时自动调用。Connection 是一个实际的 DBAPI 连接的 代理 对象。DBAPI 连接是在创建 Connection 时从连接池中检索的。
返回的对象称为 CursorResult,它引用了一个 DBAPI 游标,并提供了类似于 DBAPI 游标的获取行的方法。当所有结果行(如果有)都耗尽时,CursorResult 将关闭 DBAPI 游标。一个不返回行的 CursorResult,例如没有返回任何行的 UPDATE 语句,立即在构造时释放游标资源。
当在 with: 块的末尾关闭 Connection 时,引用的 DBAPI 连接被释放到连接池中。从数据库本身的角度来看,假设连接池有空间存储该连接以供下次使用,连接池实际上不会“关闭”连接。当将连接返回给连接池以供重用时,池化机制会在 DBAPI 连接上发出 rollback() 调用,以便删除任何事务状态或锁定(这称为 Reset On Return),并且连接准备好供下次使用。
上面的示例说明了执行文本 SQL 字符串,应该使用 text() 构造来指示我们想要使用文本 SQL。Connection.execute() 方法当然可以容纳更多内容;请参阅 Working with Data 在 SQLAlchemy 统一教程 中进行教程。
使用事务
注意
本节描述了在直接使用Engine和Connection对象时如何使用事务。当使用 SQLAlchemy ORM 时,事务控制的公共 API 是通过Session对象,该对象在内部使用Transaction对象。有关更多信息,请参阅管理事务。
按需提交
Connection对象始终在事务块的上下文中发出 SQL 语句。第一次调用Connection.execute()方法来执行 SQL 语句时,此事务会自动开始,使用一种称为autobegin的行为。事务在Connection对象的范围内保持不变,直到调用Connection.commit()或Connection.rollback()方法。在事务结束后,Connection等待再次调用Connection.execute()方法,此时它会自动重新开始。
此调用风格称为按需提交,如下面的示例所示:
with engine.connect() as connection: connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) connection.commit() # commit the transaction
在“按需提交”的风格中,我们可以在使用Connection.execute()发出的一系列其他语句中自由地调用Connection.commit()和Connection.rollback()方法;每次事务结束,并发出新语句时,都会隐式开始一个新的事务:
with engine.connect() as connection: connection.execute(text("<some statement>")) connection.commit() # commits "some statement" # new transaction starts connection.execute(text("<some other statement>")) connection.rollback() # rolls back "some other statement" # new transaction starts connection.execute(text("<a third statement>")) connection.commit() # commits "a third statement"
2.0 版本中的新功能:“按需提交”风格是 SQLAlchemy 2.0 的新功能。当使用“future”风格引擎时,它也可用于 SQLAlchemy 1.4 的“过渡”模式中。
只需开始一次
Connection对象提供了一种更明确的事务管理样式,称为仅开始一次。与“按需提交”相比,“仅开始一次”允许显式声明事务的起始点,并允许将事务本身构建为上下文管理器块,以便事务的结束变得隐式。要使用“仅开始一次”,使用Connection.begin()方法,它返回一个代表 DBAPI 事务的Transaction对象。该对象还支持通过其自己的Transaction.commit()和Transaction.rollback()方法进行显式管理,但作为首选做法,还支持上下文管理器接口,其中当块正常结束时,它将自行提交,并在引发异常时发出回滚,然后将异常传播到外部。下面说明了“仅开始一次”块的形式:
with engine.connect() as connection: with connection.begin(): connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # transaction is committed
从引擎连接和开始一次
上述“仅开始一次”块的便捷简写形式是在起始Engine对象的级别上使用Engine.begin()方法,而不是执行Engine.connect()和Connection.begin()这两个单独的步骤;Engine.begin()方法返回一个特殊的上下文管理器,内部同时维护Connection的上下文管理器以及通常由Connection.begin()方法返回的Transaction的上下文管理器:
with engine.begin() as connection: connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # transaction is committed, and Connection is released to the connection # pool
提示
在Engine.begin()块中,我们可以调用Connection.commit()或Connection.rollback()方法,这将提前结束由该块正常标记的事务。但是,如果我们这样做,就不能在Connection上进一步发出 SQL 操作,直到块结束为止:
>>> from sqlalchemy import create_engine >>> e = create_engine("sqlite://", echo=True) >>> with e.begin() as conn: ... conn.commit() ... conn.begin() 2021-11-08 09:49:07,517 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2021-11-08 09:49:07,517 INFO sqlalchemy.engine.Engine COMMIT Traceback (most recent call last): ... sqlalchemy.exc.InvalidRequestError: Can't operate on closed transaction inside context manager. Please complete the context manager before emitting further commands.
混合样式
“一次性开始”和“边执行边提交”样式可以自由混合在单个 Engine.connect() 块中,只要对 Connection.begin() 的调用不与“自动开始”行为冲突。为了实现这一点,Connection.begin() 应该在发出任何 SQL 语句之前或在直接调用之后调用 Connection.commit() 或 Connection.rollback():
with engine.connect() as connection: with connection.begin(): # run statements in a "begin once" block connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) # transaction is committed # run a new statement outside of a block. The connection # autobegins connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # commit explicitly connection.commit() # can use a "begin once" block here with connection.begin(): # run more statements connection.execute(...)
当开发使用“一次性开始”的代码时,如果事务已经“自动开始”,库将引发 InvalidRequestError。
边执行边提交
Connection 对象总是在事务块的上下文中发出 SQL 语句。当第一次调用 Connection.execute() 方法执行 SQL 语句时,将自动开始此事务,使用的是称为自动开始的行为。事务将一直保持到 Connection 对象的范围内,直到调用 Connection.commit() 或 Connection.rollback() 方法。在事务结束后,Connection 等待再次调用 Connection.execute() 方法,此时将再次自动开始。
这种调用方式称为边执行边提交,下面的示例中有所说明:
with engine.connect() as connection: connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) connection.commit() # commit the transaction
在“边执行边提交”样式中,我们可以随时调用 Connection.commit() 和 Connection.rollback() 方法,在使用 Connection.execute() 发出的其他语句序列中;每次事务结束,并发出新的语句时,都会隐式开始一个新的事务:
with engine.connect() as connection: connection.execute(text("<some statement>")) connection.commit() # commits "some statement" # new transaction starts connection.execute(text("<some other statement>")) connection.rollback() # rolls back "some other statement" # new transaction starts connection.execute(text("<a third statement>")) connection.commit() # commits "a third statement"
2.0 版本新增:“边执行边提交”样式是 SQLAlchemy 2.0 的新功能。当使用“未来”样式引擎时,它也可在 SQLAlchemy 1.4 的“过渡”模式中使用。
一次性开始
Connection对象提供了一种更明确的事务管理样式,称为begin once。与“随着操作进行提交”相比,“begin once”允许明确指定事务的起始点,并允许将事务本身构建为上下文管理器块,以便事务的结束是隐式的。要使用“begin once”,使用Connection.begin()方法,该方法返回一个表示 DBAPI 事务的Transaction对象。该对象还支持通过自己的Transaction.commit()和Transaction.rollback()方法的显式管理,但作为首选做法,还支持上下文管理器接口,在块正常结束时将自动提交,并在引发异常时发出回滚,然后将异常传播出去。下面示例说明了“begin once”块的形式:
with engine.connect() as connection: with connection.begin(): connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # transaction is committed
从引擎连接和开始一次
对于上述“begin once”块的一个便捷的缩写形式是在源Engine对象的级别上使用Engine.begin()方法,而不是执行两个分开的步骤Engine.connect()和Connection.begin();Engine.begin()方法返回一个特殊的上下文管理器,内部同时维护Connection的上下文管理器以及通常由Connection.begin()方法返回的Transaction的上下文管理器:
with engine.begin() as connection: connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # transaction is committed, and Connection is released to the connection # pool
提示
在Engine.begin()块中,我们可以调用Connection.commit()或Connection.rollback()方法,这将提前结束由块正常标记的事务。但是,如果我们这样做,直到块结束之前,Connection上不会再发出任何 SQL 操作:
>>> from sqlalchemy import create_engine >>> e = create_engine("sqlite://", echo=True) >>> with e.begin() as conn: ... conn.commit() ... conn.begin() 2021-11-08 09:49:07,517 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2021-11-08 09:49:07,517 INFO sqlalchemy.engine.Engine COMMIT Traceback (most recent call last): ... sqlalchemy.exc.InvalidRequestError: Can't operate on closed transaction inside context manager. Please complete the context manager before emitting further commands.
混合样式
“随行提交”和“一次开始”样式可以在单个 Engine.connect() 块内自由混合使用,只要对 Connection.begin() 的调用不与“自动开始”行为冲突即可。为了实现这一点,Connection.begin() 应该在发出任何 SQL 语句之前或直接在先前对 Connection.commit() 或 Connection.rollback() 的调用之后被调用:
with engine.connect() as connection: with connection.begin(): # run statements in a "begin once" block connection.execute(some_table.insert(), {"x": 7, "y": "this is some data"}) # transaction is committed # run a new statement outside of a block. The connection # autobegins connection.execute( some_other_table.insert(), {"q": 8, "p": "this is some more data"} ) # commit explicitly connection.commit() # can use a "begin once" block here with connection.begin(): # run more statements connection.execute(...)
在开发使用“一次开始”的代码时,如果事务已经“自动开始”,库将引发 InvalidRequestError。
SqlAlchemy 2.0 中文文档(四十四)(7)https://developer.aliyun.com/article/1563074