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