SqlAlchemy 2.0 中文文档(四十四)(6)

简介: SqlAlchemy 2.0 中文文档(四十四)

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.ScalarResultsqlalchemy.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 重命名为 RowRow 不再是“代理”对象,因为它包含其中的最终数据形式,现在大部分像命名元组一样操作。类似映射的功能移到了 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

返回此 RowRowMapping

此对象为行中包含的数据提供了一致的 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 484Tuple 数据类型,其中包含有关各个元素的类型信息,支持类型化的解包和属性访问。

自 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 可以通过 RowRow._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.TupleResultsqlalchemy.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 统一教程 中进行教程。

使用事务

注意

本节描述了在直接使用EngineConnection对象时如何使用事务。当使用 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

相关文章
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十四)(2)
SqlAlchemy 2.0 中文文档(四十四)
69 4
|
3月前
|
存储 缓存 数据库
SqlAlchemy 2.0 中文文档(四十四)(5)
SqlAlchemy 2.0 中文文档(四十四)
56 4
|
3月前
|
SQL 缓存 数据库连接
SqlAlchemy 2.0 中文文档(四十四)(4)
SqlAlchemy 2.0 中文文档(四十四)
44 3
|
3月前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(四十四)(9)
SqlAlchemy 2.0 中文文档(四十四)
44 3
|
3月前
|
SQL 存储 缓存
SqlAlchemy 2.0 中文文档(四十四)(8)
SqlAlchemy 2.0 中文文档(四十四)
50 0
|
3月前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(四十四)(1)
SqlAlchemy 2.0 中文文档(四十四)
75 0
|
3月前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(四十四)(7)
SqlAlchemy 2.0 中文文档(四十四)
38 0
|
3月前
|
SQL 缓存 关系型数据库
SqlAlchemy 2.0 中文文档(四十四)(3)
SqlAlchemy 2.0 中文文档(四十四)
49 0
|
3月前
|
SQL 安全 关系型数据库
SqlAlchemy 2.0 中文文档(五十三)(4)
SqlAlchemy 2.0 中文文档(五十三)
27 0
|
3月前
|
SQL 关系型数据库 数据库
SqlAlchemy 2.0 中文文档(五十三)(3)
SqlAlchemy 2.0 中文文档(五十三)
23 0