SqlAlchemy 2.0 中文文档(七十九)(2)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: SqlAlchemy 2.0 中文文档(七十九)

SqlAlchemy 2.0 中文文档(七十九)(1)https://developer.aliyun.com/article/1561101


映射器要求多态性的列在映射的可选择项中存在

在 0.6 中是一个警告,现在在 0.7 中是一个错误。给定用于 polymorphic_on 的列必须在映射的可选择项中。这是为了防止一些偶发的用户错误,例如:

mapper(SomeClass, sometable, polymorphic_on=some_lookup_table.c.id)

在这种情况下,polymorphic_on 需要在sometable列上,也许是sometable.c.some_lookup_id。有时还会出现一些“多态联合”场景,类似的错误有时也会发生。

这样的配置错误一直都是“错误”的,并且上述映射不按照指定的方式工作 - 列将被忽略。然而,在极少数情况下,这可能是向后不兼容的,因为应用程序可能一直在无意中依赖于这种行为。

#1875

DDL() 构造现在会转义百分号

以前,在 DDL() 字符串中的百分号必须进行转义,即 %% 取决于 DBAPI,对于那些接受 pyformatformat 绑定的 DBAPI(例如 psycopg2,mysql-python),这与自动执行此操作的 text() 构造不一致。现在,DDL()text() 一样进行相同的转义。

#1897

Table.c / MetaData.tables 稍微精炼了一下,不允许直接变异。

另一个领域,一些用户在进行某种方式的尝试时实际上并不按预期工作,但仍然留下了极小的机会,即某些应用程序依赖于这种行为,.c 属性在 Table 上返回的构造和 MetaData 上的 .tables 属性明确是不可变的。构造的“可变”版本现在是私有的。向 .c 添加列涉及使用 Tableappend_column() 方法,这确保了事物以适当的方式与父 Table 关联;同样,MetaData.tables 与存储在此字典中的 Table 对象有一个合同,以及一些新的簿记,跟踪所有模式名称的 set(),只有通过使用公共 Table 构造函数以及 Table.tometadata() 才能满足。

当然,ColumnCollectiondict 集合可能会在某一天实现对其所有变异方法的事件,以便在直接变异集合时发生适当的簿记,但在有人有动力实现所有这些以及数十个新单元测试之前,缩小这些集合的变异路径将确保没有应用程序试图依赖当前不支持的用法。

#1893 #1917

server_default 对所有 inserted_primary_key 值始终返回 None

server_default 出现在整数主键列上时确立了一致性。SQLA 不会预取这些值,也不会在 cursor.lastrowid(DBAPI)中返回它们。确保所有后端在 result.inserted_primary_key 中一致地返回 None - 一些后端可能之前返回过一个值。在主键列上使用 server_default 是极不寻常的。如果使用特殊函数或 SQL 表达式生成主键默认值,则应将其确定为 Python 端的“default” 而不是 server_default

对于这种情况的反射,具有 server_default 的 int PK 列的反射将“autoincrement” 标志设置为 False,除非是 PG SERIAL 列,我们检测到一个序列默认值。

#2020 #2021

sys.modules 中的 sqlalchemy.exceptions 别名被移除。

几年来,我们一直将字符串 sqlalchemy.exceptions 添加到 sys.modules 中,以便像“import sqlalchemy.exceptions”这样的语句能够正常工作。核心异常模块的名称现在已经是 exc 很长时间了,因此建议导入此模块的方式是:

from sqlalchemy import exc

对于可能已经说过 from sqlalchemy import exceptions 的应用程序,exceptions 名称仍然存在于“sqlalchemy”中,但他们也应该开始使用 exc 名称。

查询时间配方更改

虽然不是 SQLAlchemy 本身的一部分,但值得一提的是,将 ConnectionProxy 重构为新的事件系统意味着不再适用于“Timing all Queries”配方。请调整查询计时器以使用 before_cursor_execute()after_cursor_execute() 事件,在更新后的配方 UsageRecipes/Profiling 中有示例。

弃用的 API

类型上的默认构造函数不会接受参数

核心类型模块中的简单类型如 IntegerDate 等不接受参数。从 0.7b4/0.7.0 开始,接受/忽略 catchall \*args, \**kwargs 的默认构造函数已经恢复,但会发出弃用警告。

如果在核心类型如 Integer 中使用参数,可能是你打算使用特定于方言的类型,比如 sqlalchemy.dialects.mysql.INTEGER,它接受一个“display_width”参数。

compile_mappers() 重命名为 configure_mappers(),简化配置内部

这个系统从最初是一个小型的、实现在单个映射器本地的东西,命名不当,逐渐演变成了更像是一个全局“注册表”级别的功能,命名不当,因此我们通过将实现移出 Mapper 并将其重命名为 configure_mappers() 来修复这两个问题。当然,通常情况下应用程序不需要调用 configure_mappers(),因为这个过程是根据需要的,一旦通过属性或查询访问需要映射时就会发生。

#1966

核心监听器/代理被事件监听器取代

PoolListenerConnectionProxyDDLElement.execute_at 被分别替代为 event.listen(),使用 PoolEventsEngineEventsDDLEvents 分发目标。

ORM 扩展被事件监听��取代

MapperExtensionAttributeExtensionSessionExtension 被分别替代为 event.listen(),使用 MapperEvents/InstanceEventsAttributeEventsSessionEvents 分发目标。

在 MySQL 中,将字符串发送到 select() 的 ‘distinct’ 应该通过前缀来完成

这个晦涩的特性允许在 MySQL 后端中使用这种模式:

select([mytable], distinct="ALL", prefixes=["HIGH_PRIORITY"])

对于非标准或不寻常的前缀,应该使用 prefixes 关键字或 prefix_with() 方法:

select([mytable]).prefix_with("HIGH_PRIORITY", "ALL")

useexistingextend_existingkeep_existing 取代

Table 上的 useexisting 标志已被新的一对标志 keep_existingextend_existing 取代。extend_existing 等同于 useexisting - 返回现有的 Table,并添加额外的构造元素。使用 keep_existing,返回现有的 Table,但不添加额外的构造元素 - 这些元素仅在新创建 Table 时应用。

不兼容的后向 API 更改

传递给 bindparam() 的可调用对象不会被评估 - 影响 Beaker 示例

#1950

请注意,这影响了 Beaker 缓存示例,其中 _params_from_query() 函数的工作需要进行轻微调整。如果您正在使用 Beaker 示例中的代码,则应用此更改。

types.type_map 现在是私有的,types._type_map

我们注意到一些用户在 sqlalchemy.types 内部利用这个字典作为将 Python 类型与 SQL 类型关联的快捷方式。我们无法保证这个字典的内容或格式,并且将 Python 类型一对一关联的业务有一些灰色地带,最好由各个应用程序自行决定,因此我们已经强调了这个属性。

#1870

将独立 alias() 函数的 alias 关键字参数重命名为 name

这样关键字参数 name 与所有 FromClause 对象上的 alias() 方法以及 Query.subquery() 上的 name 参数匹配。

只有使用独立的 alias() 函数,而不是方法绑定函数,并且使用显式关键字名称 alias 而不是位置上的别名名称的代码需要在这里进行修改。

非公共 Pool 方法已加下划线

所有 Pool 及其子类的所有不打算公开使用的方法都已改名为下划线。它们以前没有这样命名是一个错误。

现在下划线或已移除的池化方法:

Pool.create_connection() -> Pool._create_connection()

Pool.do_get() -> Pool._do_get()

Pool.do_return_conn() -> Pool._do_return_conn()

Pool.do_return_invalid() -> 已移除,未被使用

Pool.return_conn() -> Pool._return_conn()

Pool.get() -> Pool._get(), 公共 API 是 Pool.connect()

SingletonThreadPool.cleanup() -> _cleanup()

SingletonThreadPool.dispose_local() -> 已移除,使用 conn.invalidate()

#1982

以前弃用,现在已移除

Query.join(), Query.outerjoin(), eagerload(), eagerload_all(), 其他不再允许将属性列表作为参数

从 0.5 开始,将属性或属性名称列表传递给 Query.join, eagerload() 等已被弃用:

# old way, deprecated since 0.5
session.query(Houses).join([Houses.rooms, Room.closets])
session.query(Houses).options(eagerload_all([Houses.rooms, Room.closets]))

这些方法在 0.5 系列中都接受 *args:

# current way, in place since 0.5
session.query(Houses).join(Houses.rooms, Room.closets)
session.query(Houses).options(eagerload_all(Houses.rooms, Room.closets))

ScopedSession.mapper 已移除

这一功能提供了一个映射器扩展,将基于类的功能与特定的ScopedSession链接起来,特别是提供了这样的行为,即新对象实例将自动与该会话关联。 该功能被教程和框架过度使用,导致用户混淆,因为其隐式行为,并在 0.5.5 中被弃用。 复制其功能的技术在[wiki:UsageRecipes/SessionAwareMapper]中。

介绍

本指南介绍了 SQLAlchemy 版本 0.7 中的新功能,并记录了影响用户将其应用程序从 SQLAlchemy 0.6 系列迁移到 0.7 的更改。

尽可能地,更改是以不破坏为 0.6 构建的应用程序的兼容性的方式进行的。 必然不向后兼容的更改非常少,除了一个,即对可变属性默认值的更改,应该影响极小部分应用程序 - 许多更改涉及非公共 API 和未记录的一些用户可能一直在尝试使用的黑客技巧。

还有第二个更小的一类不向后兼容的更改也有文档记录。 这类更改涉及那些自 0.5 版本以来已被弃用并自弃用以来一直引发警告的功能和行为。  这些更改只会影响仍在使用 0.4 或早期 0.5 样式 API 的应用程序。 随着项目的成熟,我们在 0.x  级别发布中有越来越少这类更改,这是由于我们的 API 具有越来越少的功能,这些功能对于它们旨在解决的用例来说不太理想。

在 SQLAlchemy 0.7 中,一系列现有功能已被取代。 “取代”和“弃用”之间没有太大区别,只是前者对旧功能的暗示要被删除的可能性较小。 在 0.7 中,像synonymcomparable_property以及所有Extension和其他事件类等功能已被取代。 但是这些“取代”功能已被重新实现,使得它们的实现主要存在于核心 ORM 代码之外,因此它们的持续“挂在”不会影响 SQLAlchemy 进一步简化和完善其内部的能力,并且我们预计它们将在可预见的未来保留在 API 中。

新功能

新事件系统

SQLAlchemy 早期开始使用 MapperExtension 类,该类提供了对映射器持久性周期的钩子。随着 SQLAlchemy 快速变得更加组件化,将映射器推入更专注的配置角色,许多更多的“扩展”、“监听器”和“代理”类出现,以以一种临时的方式解决各种活动拦截用例。其中一部分是由活动的分歧驱动的;ConnectionProxy 对象希望提供一个重写语句和参数的系统;AttributeExtension 提供了一个替换传入值的系统,而 DDL 对象具有可以切换到方言敏感可调用对象的事件。

0.7 重新实现了几乎所有这些插件点,采用了一种新的、统一的方法,保留了不同系统的所有功能,提供了更多的灵活性和更少的样板代码,性能更好,并消除了需要为每个事件子系统学习根本不同的 API 的必要性。现有的类 MapperExtensionSessionExtensionAttributeExtensionConnectionProxyPoolListener 以及 DDLElement.execute_at 方法已被弃用,现在根据新系统实现 - 这些 API 仍然完全可用,并预计将在可预见的未来保持不变。

新方法使用命名事件和用户定义的可调用对象将活动与事件关联起来。API 的外观和感觉受到了 JQuery、Blinker 和  Hibernate 等多样化来源的驱动,并且在与数十位用户进行的 Twitter  会议期间进行了多次修改,这似乎比邮件列表对这类问题的回应率要高得多。

它还具有一个开放式的目标规范系统,允许将事件与 API 类关联,例如所有 SessionEngine 对象,以及与 API 类的特定实例关联,例如特定的 PoolMapper,以及与用户定义的类相关的对象,例如映射的类,或者特定子类的实例上的某个属性。个别监听器子系统可以将包装器应用于传入的用户定义的监听器函数,从而修改它们的调用方式 - 映射器事件可以接收被操作对象的实例,或者其底层的 InstanceState 对象。属性事件可以选择是否要负责返回一个新值。

几个系统现在基于新的事件 API 构建,包括新的“可变属性” API 以及复合属性。对事件的更大强调还导致引入了一些新事件,包括属性过期和刷新操作,pickle 加载/转储操作,完成的映射器构造操作。

另请参见

事件

#1902

混合属性,实现/取代了 synonym()、comparable_property()

“派生属性”示例现在已经转变为官方扩展。synonym()的典型用例是为映射列提供描述符访问;comparable_property()的用例是能够从任何描述符返回PropComparator。实际上,“派生”的方法更易于使用,更具可扩展性,用几十行纯 Python 实现几乎不需要导入,甚至不需要 ORM 核心意识到它。该功能现在被称为“混合属性”扩展。

synonym()comparable_property()仍然是 ORM 的一部分,尽管它们的实现已经移出,建立在类似于混合扩展的方法之上,以便核心 ORM 映射器/查询/属性模块在其他情况下并不真正意识到它们。

另请参阅

混合属性

#1903

速度增强

与所有主要 SQLA 版本一样,通过内部进行广泛的遍历以减少开销和调用次数,进一步减少了在常见情况下所需的工作量。此版本的亮点包括:

  • 刷新过程现在将 INSERT 语句捆绑成批次供cursor.executemany()执行,对于主键已经存在的行。特别是在连接表继承配置中通常适用于“子”表,这意味着对于大量连接表对象的大批量插入,可以将对cursor.execute的调用次数减半,从而允许本地 DBAPI 优化对传递给cursor.executemany()的语句进行(例如重用准备好的语句)。
  • 当访问已加载的相关对象的多对一引用时,调用的代码路径已经大大简化。直接检查标识映射,无需首先生成新的Query对象,这在访问成千上万个内存中的多对一时是昂贵的。对于大多数延迟属性加载,也不再使用每次构造的“加载器”对象。
  • 重新编写组合使得在映射器内部访问映射属性时可以走更短的代码路径。
  • 新的内联属性访问函数取代了以前在“保存-更新”和其他级联操作需要在属性关联的所有数据成员范围内级联时使用“history”的做法。这减少了为这个速度关键操作生成新的History对象的开销。
  • ExecutionContext的内部,即对语句执行的对象,已经被内联和简化。
  • 由类型为每个语句执行生成的bind_processor()result_processor()可调用现在被缓存(谨慎地,以避免临时类型和方言的内存泄漏)为该类型的寿命,进一步减少每个语句调用的开销。
  • 特定Compiled语句实例的“绑定处理器”集合也缓存在Compiled对象上,进一步利用了由刷新过程使用的“编译缓存”来重复使用相同的 INSERT、UPDATE、DELETE 语句的编译形式。

包括一个示例基准脚本的调用次数减少演示在techspot.zzzeek.org/2010/12/12/a-tale-of-three- profiles/

复合已重写

“composite”功能已被重写,类似于synonym()comparable_property(),使用了基于描述符和事件的轻量级实现,而不是构建到 ORM 内部。这样做可以从映射器/工作单元内部删除一些延迟,并简化复合属性的工作方式。复合属性现在不再隐藏其构建在其上的基础列,这些列现在保持为常规属性。复合还可以充当relationship()以及Column()属性的代理。

复合的主要不兼容性变化是它们不再使用mutable=True系统来检测原地突变。请使用Mutation Tracking扩展来建立对现有复合使用的原地更改事件。

另请参阅

复合列类型

Mutation Tracking

#2008 #2024

更简洁的查询.join(target, onclause)形式

向具有显式 onclause 的目标发出query.join()的默认方法现在是:

query.join(SomeClass, SomeClass.id == ParentClass.some_id)

在 0.6 版本中,这种用法被认为是错误的,因为join()接受多个参数对应于多个 JOIN 子句 -  两个参数形式需要在元组中以消除单参数和双参数连接目标之间的歧义。在 0.6  中间,我们为这种特定的调用风格添加了检测和错误消息,因为它是如此常见。在 0.7  中,由于我们无论如何都在检测确切的模式,并且因为不得不无缘无故地输入一个元组是极其恼人的,非元组方法现在成为“正常”做法。与单个连接情况相比,“多个  JOIN”用例极为罕见,而如今多个连接更清晰地表示为多次调用join()

元组形式将保留以确保向后兼容性。

请注意,所有其他形式的query.join()保持不变:

query.join(MyClass.somerelation)
query.join("somerelation")
query.join(MyTarget)
# ... etc

使用连接查询

#1923

突变事件扩展,取代“mutable=True”

一个新的扩展,Mutation Tracking,提供了一种机制,用户定义的数据类型可以向拥有的父级或父级提供更改事件。该扩展包括一种用于标量数据库值的方法,例如由PickleTypepostgresql.ARRAY或其他自定义MutableType类管理的值,以及一种用于 ORM “组合”配置的方法,这些配置使用composite()

另请参阅

Mutation Tracking

NULLS FIRST / NULLS LAST 操作符

这些操作符作为asc()desc()操作符的扩展实现,称为nullsfirst()nullslast()

另请参阅

nullsfirst()

nullslast()

#723

select.distinct()、query.distinct()接受 PostgreSQL DISTINCT ON 的*args

通过将表达式列表传递给select()distinct关键字参数,现在select()Querydistinct()方法接受位置参数,当使用 PostgreSQL 后端时,这些参数将被渲染为 DISTINCT ON。

distinct()

Query.distinct()

#1069

Index()可以内联放置在Table__table_args__

Index() 构造可以与 Table 定义内联创建,使用字符串作为列名,作为在 Table 外创建索引的替代方法。即:

Table(
    "mytable",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("name", String(50), nullable=False),
    Index("idx_name", "name"),
)

这里的主要原因是为了声明式__table_args__的好处,特别是在与 mixins 一起使用时:

class HasNameMixin(object):
    name = Column("name", String(50), nullable=False)
    @declared_attr
    def __table_args__(cls):
        return (Index("name"), {})
class User(HasNameMixin, Base):
    __tablename__ = "user"
    id = Column("id", Integer, primary_key=True)

Indexes

窗口函数 SQL 构造

“窗口函数”向语句提供有关生成的结果集的信息。这允许根据诸如“行号”、“排名”等各种条件进行筛选。它们至少被 PostgreSQL、SQL Server 和 Oracle 支持,可能还有其他数据库。

关于窗口函数的最佳介绍在 PostgreSQL 的网站上,自从 8.4 版本以来就支持窗口函数:

www.postgresql.org/docs/current/static/tutorial-window.html

SQLAlchemy 提供了一个简单的构造,通常通过现有的函数子句调用,使用over()方法,接受order_bypartition_by关键字参数。下面我们复制了 PG 教程中的第一个示例:

from sqlalchemy.sql import table, column, select, func
empsalary = table("empsalary", column("depname"), column("empno"), column("salary"))
s = select(
    [
        empsalary,
        func.avg(empsalary.c.salary)
        .over(partition_by=empsalary.c.depname)
        .label("avg"),
    ]
)
print(s)

SQL:

SELECT  empsalary.depname,  empsalary.empno,  empsalary.salary,
avg(empsalary.salary)  OVER  (PARTITION  BY  empsalary.depname)  AS  avg
FROM  empsalary

sqlalchemy.sql.expression.over

#1844

Connection 上的 execution_options()接受“isolation_level”参数

这将为单个Connection设置事务隔离级别,直到该Connection关闭并其底层 DBAPI 资源返回到连接池,此时隔离级别将重置为默认值。默认的隔离级别是使用create_engine()isolation_level参数设置的。

事务隔离支持目前仅由 PostgreSQL 和 SQLite 后端支持。

execution_options()

#2001

TypeDecorator与整数主键列一起使用

一个TypeDecorator,它扩展了Integer的行为,可以与主键列一起使用。Column的“autoincrement”特性现在将识别到底层数据库列仍然是整数,以便lastrowid机制继续正常工作。TypeDecorator本身将其结果值处理器应用于新生成的主键,包括通过 DBAPI cursor.lastrowid访问器接收到的主键。

#2005 #2006

TypeDecorator存在于“sqlalchemy”导入空间中

不再需要从sqlalchemy.types导入此内容,现在在sqlalchemy中有镜像。

新方言

已添加方言:

  • 一个用于 Drizzle 数据库的 MySQLdb 驱动程序:
    Drizzle
  • 支持 pymysql DBAPI:
    pymsql Notes
  • psycopg2 现在与 Python 3 兼容

新事件系统

SQLAlchemy 早期开始使用MapperExtension类,该类提供了对映射器持久化周期的钩子。随着 SQLAlchemy 迅速变得更加组件化,将映射器推入更专注的配置角色,许多更多的“extension”、“listener”和“proxy”类出现,以解决各种活动拦截用例。部分原因是由活动的分歧驱动的;ConnectionProxy对象希望提供一个重写语句和参数的系统;AttributeExtension提供了一个替换传入值的系统,而DDL对象具有可以切换为方言敏感可调用的事件。

0.7 版本使用了一种新的、统一的方法重新实现了几乎所有这些插件点,保留了不同系统的所有功能,提供了更多的灵活性和更少的样板代码,性能更好,并且消除了需要为每个事件子系统学习根本不同的 API 的必要性。预先存在的类MapperExtensionSessionExtensionAttributeExtensionConnectionProxyPoolListener以及DDLElement.execute_at方法已被弃用,现在根据新系统实现 - 这些 API 仍然完全可用,并且预计将在可预见的未来保持不变。

新方法使用命名事件和用户定义的可调用对象将活动与事件关联起来。API 的外观和感觉受到了 JQuery、Blinder 和  Hibernate 等多样化来源的驱动,并且在与数十名用户进行的会议期间多次进行了修改,这些会议在 Twitter  上的响应率似乎比邮件列表更高。

它还具有一种开放式的目标规范系统,允许将事件与 API 类关联,例如所有的SessionEngine对象,以及特定 API 类的实例,例如特定的PoolMapper,以及相关对象,如映射的用户定义类,或者特定子类的映射父类实例的特定属性。各个监听器子系统可以对传入的用户定义监听器函数应用包装器,修改它们的调用方式 - 映射事件可以接收被操作对象的实例,或者其底层的InstanceState对象。属性事件可以选择是否要负责返回一个新值。

几个系统现在建立在新的事件 API 之上,包括新的“可变属性”API 以及复合属性。对事件的更大强调还导致引入了一些新事件,包括属性过期和刷新操作,pickle 加载/转储操作,完成的映射器构造操作。

另请参阅

事件

#1902

混合属性,实现/取代了 synonym()、comparable_property()

“派生属性”示例现在已成为官方扩展。synonym()的典型用例是为映射列提供描述符访问;comparable_property()的用例是能够从任何描述符返回PropComparator。实际上,“派生”的方法更容易使用,更具可扩展性,用几十行纯 Python 实现,几乎不需要导入,甚至不需要 ORM 核心知道它。该功能现在被称为“混合属性”扩展。

synonym()comparable_property()仍然是 ORM 的一部分,尽管它们的实现已经移出,建立在类似于混合扩展的方法上,因此核心 ORM 映射器/查询/属性模块在其他情况下并不真正意识到它们。

另请参见

混合属性

#1903


SqlAlchemy 2.0 中文文档(七十九)(3)https://developer.aliyun.com/article/1561105

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7天前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(七十一)(4)
SqlAlchemy 2.0 中文文档(七十一)
12 1
|
7天前
|
Oracle 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(七十一)(1)
SqlAlchemy 2.0 中文文档(七十一)
9 1
|
10天前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(七十九)(5)
SqlAlchemy 2.0 中文文档(七十九)
11 2
|
10天前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(七十六)(1)
SqlAlchemy 2.0 中文文档(七十六)
12 2
|
10天前
|
SQL 关系型数据库 MySQL
SqlAlchemy 2.0 中文文档(七十六)(2)
SqlAlchemy 2.0 中文文档(七十六)
19 2
|
11天前
|
SQL 存储 缓存
SqlAlchemy 2.0 中文文档(八十一)(1)
SqlAlchemy 2.0 中文文档(八十一)
13 2
|
11天前
|
SQL 缓存 API
SqlAlchemy 2.0 中文文档(八十一)(3)
SqlAlchemy 2.0 中文文档(八十一)
14 1
|
11天前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(八十一)(2)
SqlAlchemy 2.0 中文文档(八十一)
18 1
|
11天前
|
存储 SQL Java
SqlAlchemy 2.0 中文文档(八十一)(4)
SqlAlchemy 2.0 中文文档(八十一)
16 1
|
11天前
|
SQL Oracle 关系型数据库
SqlAlchemy 2.0 中文文档(八十一)(5)
SqlAlchemy 2.0 中文文档(八十一)
16 1