SqlAlchemy 2.0 中文文档(七十三)(4)https://developer.aliyun.com/article/1562226
核心关键变化
完全删除将字符串 SQL 片段强制转换为 text()
首次在版本 1.0 中添加的警告,描述在将完整 SQL 片段强制转换为 text()时发出的警告,现在已转换为异常。对于像Query.filter()
和Select.order_by()
等方法传递的字符串片段自动转换为text()
构造的持续关注,尽管这已发出警告。在Select.order_by()
、Query.order_by()
、Select.group_by()
和Query.group_by()
的情况下,字符串标签或列名仍然解析为相应的表达式构造,但如果解析失败,则会引发CompileError
,从而防止直接呈现原始 SQL 文本。
#4481 ### “线程本地”引擎策略已弃用
“线程本地引擎策略”是在 SQLAlchemy 0.2 左右添加的,作为解决 SQLAlchemy 0.1 中操作的标准方式的问题的解决方案,可以总结为“线程本地一切”,发现存在不足。回顾起来,似乎相当荒谬,SQLAlchemy 的首次发布在各个方面都是“alpha”,却担心太多用户已经定居在现有 API 上,无法简单地更改它。
SQLAlchemy 的原始用法模型如下:
engine.begin() table.insert().execute(parameters) result = table.select().execute() table.update().execute(parameters) engine.commit()
在几个月的实际使用后,很明显,假装“连接”或“事务”是一个隐藏的实现细节是一个坏主意,特别是当有人需要同时处理多个数据库连接时。因此,我们今天看到的使用范式被引入,减去了上下文管理器,因为它们在 Python 中尚不存在:
conn = engine.connect() try: trans = conn.begin() conn.execute(table.insert(), parameters) result = conn.execute(table.select()) conn.execute(table.update(), parameters) trans.commit() except: trans.rollback() raise finally: conn.close()
上述范式是人们所需要的,但由于它仍然有点冗长(因为没有上下文管理器),因此保留了旧的工作方式,并成为线程本地引擎策略。
今天,使用 Core 更加简洁,甚至比原始模式更加简洁,这要归功于上下文管理器:
with engine.begin() as conn: conn.execute(table.insert(), parameters) result = conn.execute(table.select()) conn.execute(table.update(), parameters)
此时,仍依赖“threadlocal”风格的任何剩余代码将通过此弃用来鼓励现代化 - 该功能应在下一个主要系列的 SQLAlchemy 中完全移除,例如 1.4 版。连接池参数Pool.use_threadlocal
也已弃用,因为在大多数情况下实际上没有任何效果,Engine.contextual_connect()
方法也是如此,该方法通常与Engine.connect()
方法是同义词,除非使用了 threadlocal 引擎。
#4393 ### convert_unicode 参数已弃用
参数String.convert_unicode
和create_engine.convert_unicode
已弃用。这些参数的目的是指示 SQLAlchemy 确保在 Python 2 下传递给数据库之前对传入的 Python Unicode 对象进行编码为字节字符串,并期望从数据库返回的字节字符串转换回 Python Unicode 对象。在 Python 3 之前的时代,要做到这一点是一件非常艰巨的事情,因为几乎所有 Python DBAPI 默认情况下都没有启用 Unicode 支持,并且大多数都存在与它们提供的 Unicode 扩展相关的主要问题。最终,SQLAlchemy 添加了 C 扩展,这些扩展的主要目的之一是加快结果集中的 Unicode 解码过程。
一旦引入了 Python 3,DBAPI 开始更全面地支持 Unicode,并且更重要的是,默认情况下支持 Unicode。然而,特定 DBAPI 在何种条件下会或不会从结果返回 Unicode 数据,以及接受 Python Unicode 值作为参数的条件仍然非常复杂。这标志着“convert_unicode”标志开始过时,因为它们不再足以确保仅在需要时进行编码/解码,而不是在不需要时进行。相反,“convert_unicode”开始被 dialects 自动检测。这一部分可以在引擎第一次连接时发出的“SELECT ‘test plain returns’”和“SELECT ‘test_unicode_returns’”SQL 中看到;方言正在测试当前 DBAPI 及其当前设置和后端数据库连接是否默认返回 Unicode。
结果是,不再需要在任何情况下使用“convert_unicode”标志,如果需要,SQLAlchemy 项目需要知道这些情况及其原因。目前,在所有主要数据库上,使用该标志的 Unicode 往返测试通过了数百次,因此相当有把握地认为它们不再需要,除非是在争议性的非使用情况,例如访问来自传统数据库的错误编码数据,最好使用自定义类型。
#4393 ### 完全移除将字符串 SQL 片段强制转换为 text()
在 1.0 版本中首次添加的警告,描述在将完整 SQL 片段强制转换为 text() 时发出的警告,现已转换为异常。对于将字符串片段传递给诸如Query.filter()
和 Select.order_by()
等方法的自动转换成text()
构造的情况仍然存在持续的担忧,尽管已发出警告。对于Select.order_by()
、Query.order_by()
、Select.group_by()
和 Query.group_by()
,字符串标签或列名仍然解析为相应的表达式构造,但如果解析失败,则引发CompileError
,从而防止原始 SQL 文本直接呈现。
“threadlocal” 引擎策略已弃用
“threadlocal 引擎策略” 是在 SQLAlchemy 0.2 左右添加的,作为 SQLAlchemy 0.1 中标准操作方式的解决方案,这种方式可以总结为“threadlocal everything”,但后来发现存在不足之处。回顾起来,很荒谬的是,即使 SQLAlchemy 的第一个版本在各个方面都是“alpha”版本,仍然担心已有太多用户已经习惯了现有的 API 以至于不能轻易更改。
SQLAlchemy 的原始使用模型如下:
engine.begin() table.insert().execute(parameters) result = table.select().execute() table.update().execute(parameters) engine.commit()
经过几个月的实际使用,很明显,假装“连接”或“事务”是一个隐藏的实现细节是一个坏主意,特别是当有人需要同时处理多个数据库连接时。因此,我们今天看到的使用范式被引入,减去了上下文管理器,因为它们在 Python 中尚不存在:
conn = engine.connect() try: trans = conn.begin() conn.execute(table.insert(), parameters) result = conn.execute(table.select()) conn.execute(table.update(), parameters) trans.commit() except: trans.rollback() raise finally: conn.close()
上述范式是人们所需要的,但由于仍然有点啰嗦(因为没有上下文管理器),旧的工作方式也被保留下来,并成为线程本地引擎策略。
今天,使用 Core 要简洁得多,甚至比原始模式更简洁,这要归功于上下文管理器:
with engine.begin() as conn: conn.execute(table.insert(), parameters) result = conn.execute(table.select()) conn.execute(table.update(), parameters)
此时,任何仍然依赖“threadlocal”风格的代码都将通过此弃用被鼓励进行现代化 - 该功能应在下一个主要的 SQLAlchemy 系列(例如 1.4)中完全移除。连接池参数Pool.use_threadlocal
也被弃用,因为在大多数情况下实际上没有任何效果,Engine.contextual_connect()
方法也是如此,该方法通常与Engine.connect()
方法是同义的,除非使用线程本地引擎。
convert_unicode 参数已弃用
参数String.convert_unicode
和create_engine.convert_unicode
已被弃用。这些参数的目的是指示 SQLAlchemy 在将 Python 2 中的传入 Unicode 对象传递到数据库之前确保对其进行字节串编码,并期望从数据库接收字节串并将其转换回 Python Unicode 对象。在 Python 3 之前的时代,要做到这一点是一个巨大的挑战,因为几乎所有的 Python DBAPI 默认情况下都没有启用 Unicode 支持,并且大多数都存在与其提供的 Unicode 扩展相关的主要问题。最终,SQLAlchemy 添加了 C 扩展,其中这些扩展的主要目的之一是加速结果集中的 Unicode 解码过程。
一旦引入了 Python 3,DBAPI 开始更全面地支持 Unicode,更重要的是,默认情况下支持 Unicode。然而,特定 DBAPI 是否返回 Unicode 数据以及接受 Python Unicode 值作为参数的条件仍然非常复杂。这标志着“convert_unicode”标志开始过时,因为它们不再足以确保仅在需要时进行编码/解码,而不是在不需要时进行。相反,“convert_unicode”开始由方言自动检测。可以从引擎第一次连接时发出的 SQL “SELECT ‘test plain returns’” 和 “SELECT ‘test_unicode_returns’” 中看到其中一部分;方言正在测试当前 DBAPI 与其当前设置和后端数据库连接是否默认返回 Unicode。
最终结果是,在任何情况下,用户对“convert_unicode”标志的使用都不再需要,并且如果需要,SQLAlchemy 项目需要知道这些情况以及原因。当前,在所有主要数据库上,通过了数百个 Unicode 往返测试,而不使用此标志,因此相当有信心不再需要它们,除非在可争议的非使用情况下,例如访问来自遗留数据库的错误编码数据,此时最好使用自定义类型。
方言改进和更改 - PostgreSQL
为 PostgreSQL 分区表添加了基本的反射支持
SQLAlchemy 可以在 PostgreSQL CREATE TABLE 语句中使用 postgresql_partition_by
标志渲染“PARTITION BY”序列,该标志在版本 1.2.6 中添加。然而,'p'
类型直到现在都不是反射查询的一部分。
给定这样一个模式:
dv = Table( "data_values", metadata_obj, Column("modulus", Integer, nullable=False), Column("data", String(30)), postgresql_partition_by="range(modulus)", ) sa.event.listen( dv, "after_create", sa.DDL( "CREATE TABLE data_values_4_10 PARTITION OF data_values " "FOR VALUES FROM (4) TO (10)" ), )
两个表名 'data_values'
和 'data_values_4_10'
将通过 Inspector.get_table_names()
返回,并且列也将通过 Inspector.get_columns('data_values')
和 Inspector.get_columns('data_values_4_10')
返回。这也适用于对这些表使用 Table(..., autoload=True)
。
#4237 ### 为 PostgreSQL 分区表添加了基本的反射支持
SQLAlchemy 可以在 PostgreSQL CREATE TABLE 语句中使用 postgresql_partition_by
标志渲染“PARTITION BY”序列,该标志在版本 1.2.6 中添加。然而,'p'
类型直到现在都不是反射查询的一部分。
给定这样一个模式:
dv = Table( "data_values", metadata_obj, Column("modulus", Integer, nullable=False), Column("data", String(30)), postgresql_partition_by="range(modulus)", ) sa.event.listen( dv, "after_create", sa.DDL( "CREATE TABLE data_values_4_10 PARTITION OF data_values " "FOR VALUES FROM (4) TO (10)" ), )
两个表名'data_values'
和'data_values_4_10'
将从Inspector.get_table_names()
返回,并且还将从Inspector.get_columns('data_values')
以及Inspector.get_columns('data_values_4_10')
返回列。这也适用于使用这些表的Table(..., autoload=True)
。
方言改进和变化 - MySQL
协议级别的 ping 现在用于预先 ping
包括 mysqlclient、python-mysql、PyMySQL 和 mysql-connector-python 在内的 MySQL 方言现在使用connection.ping()
方法进行池预 ping 功能,详细信息请参见断开处理 - 悲观。这比以前在连接上发出“SELECT 1”的方法要轻量得多。 ### 控制 ON DUPLICATE KEY UPDATE 中参数顺序
ON DUPLICATE KEY UPDATE
子句中 UPDATE 参数的顺序现在可以通过传递一个 2 元组列表来明确排序:
from sqlalchemy.dialects.mysql import insert insert_stmt = insert(my_table).values(id="some_existing_id", data="inserted value") on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update( [ ("data", "some data"), ("updated_at", func.current_timestamp()), ], )
参见
INSERT…ON DUPLICATE KEY UPDATE (Upsert) ### 协议级别的 ping 现在用于预先 ping
包括 mysqlclient、python-mysql、PyMySQL 和 mysql-connector-python 在内的 MySQL 方言现在使用connection.ping()
方法进行池预 ping 功能,详细信息请参见断开处理 - 悲观。这比以前在连接上发出“SELECT 1”的方法要轻量得多。
控制 ON DUPLICATE KEY UPDATE 中参数顺序
ON DUPLICATE KEY UPDATE
子句中 UPDATE 参数的顺序现在可以通过传递一个 2 元组列表来明确排序:
from sqlalchemy.dialects.mysql import insert insert_stmt = insert(my_table).values(id="some_existing_id", data="inserted value") on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update( [ ("data", "some data"), ("updated_at", func.current_timestamp()), ], )
参见
INSERT…ON DUPLICATE KEY UPDATE (Upsert)
方言改进和变化 - SQLite
对 SQLite JSON 的支持已添加
添加了一个新的数据类型JSON
,它代表了JSON
基础数据类型的 SQLite 的 json 成员访问函数。实现使用 SQLite 的JSON_EXTRACT
和JSON_QUOTE
函数来提供基本的 JSON 支持。
请注意,数据库中呈现的数据类型本身的名称是“JSON”。这将创建一个带有“numeric”亲和力的 SQLite 数据类型,通常情况下不应该成为问题,除非是由单个整数值组成的 JSON 值的情况。尽管如此,根据 SQLite 自己文档中的示例www.sqlite.org/json1.html
,名称 JSON 正在被用于其熟悉性。
#3850 ### 增加对 SQLite 约束中 ON CONFLICT 的支持
SQLite 支持一个非标准的 ON CONFLICT 子句,可以为独立约束以及一些列内约束(如 NOT NULL)指定。通过向诸如UniqueConstraint
之类的对象添加sqlite_on_conflict
关键字以及几个Column
-特定的变体:
some_table = Table( "some_table", metadata_obj, Column("id", Integer, primary_key=True, sqlite_on_conflict_primary_key="FAIL"), Column("data", Integer), UniqueConstraint("id", "data", sqlite_on_conflict="IGNORE"), )
上述表在 CREATE TABLE 语句中呈现为:
CREATE TABLE some_table ( id INTEGER NOT NULL, data INTEGER, PRIMARY KEY (id) ON CONFLICT FAIL, UNIQUE (id, data) ON CONFLICT IGNORE )
另请参阅
ON CONFLICT 支持约束
#4360 ### 增加对 SQLite JSON 的支持
添加了一个新的数据类型JSON
,该数据类型代表JSON
基本数据类型的 SQLite 的 json 成员访问函数。该实现使用 SQLite 的JSON_EXTRACT
和JSON_QUOTE
函数来提供基本的 JSON 支持。
注意,数据库中呈现的数据类型本身的名称是“JSON”。这将创建一个带有“数字”亲和力的 SQLite 数据类型,这通常不应该是问题,除非 JSON 值仅包含单个整数值。尽管如此,根据 SQLite 自己文档中的示例,www.sqlite.org/json1.html
中使用了 JSON 这个名字以保持熟悉性。
增加对 SQLite 约束中 ON CONFLICT 的支持
SQLite 支持一个非标准的 ON CONFLICT 子句,可以为独立约束以及一些列内约束(如 NOT NULL)指定。通过向诸如UniqueConstraint
之类的对象添加sqlite_on_conflict
关键字以及几个Column
-特定的变体,已为这些子句添加了支持:
some_table = Table( "some_table", metadata_obj, Column("id", Integer, primary_key=True, sqlite_on_conflict_primary_key="FAIL"), Column("data", Integer), UniqueConstraint("id", "data", sqlite_on_conflict="IGNORE"), )
上述表在 CREATE TABLE 语句中呈现为:
CREATE TABLE some_table ( id INTEGER NOT NULL, data INTEGER, PRIMARY KEY (id) ON CONFLICT FAIL, UNIQUE (id, data) ON CONFLICT IGNORE )
另请参阅
ON CONFLICT 支持约束
方言改进和更改 - Oracle
对于通用 unicode,国家字符数据类型被减弱,可通过选项重新启用
现在,默认情况下,Unicode
和 UnicodeText
数据类型现在对应于 Oracle 上的 VARCHAR2
和 CLOB
数据类型,而不是 NVARCHAR2
和 NCLOB
(也称为“国家”字符集类型)。这将在诸如它们在CREATE TABLE
语句中的呈现方式等行为中看到,以及当使用Unicode
或UnicodeText
绑定参数时,不会传递任何类型对象给setinputsizes()
;cx_Oracle 会原生处理字符串值。这种变化基于 cx_Oracle 的维护者的建议,即 Oracle 中的“国家”数据类型在很大程度上已经过时且性能不佳。它们还会在某些情况下干扰,比如应用于像trunc()
这样的函数的格式说明符时。
当数据库不使用符合 Unicode 标准的字符集时,可能需要使用NVARCHAR2
和相关类型的情况。在这种情况下,可以将标志use_nchar_for_unicode
传递给create_engine()
以重新启用旧行为。
如往常一样,明确使用NVARCHAR2
和NCLOB
数据类型将继续使用NVARCHAR2
和NCLOB
,包��在 DDL 中以及处理带有 cx_Oracle 的setinputsizes()
的绑定参数时。
在读取方面,在 Python 2 下已经添加了对 CHAR/VARCHAR/CLOB 结果行的自动 Unicode 转换,以匹配 Python 3 下 cx_Oracle 的行为。为了减轻 cx_Oracle 方言在 Python 2 下先前具有的性能损失,SQLAlchemy 在 Python 2 下使用非常高效(当构建 C 扩展时)的本地 Unicode 处理程序。可以通过将coerce_to_unicode
标志设置为 False 来禁用自动 Unicode 强制转换。此标志现在默认为 True,并适用于所有在结果集中返回的字符串数据,这些数据不明确位于Unicode
或 Oracle 的 NVARCHAR2/NCHAR/NCLOB 数据类型下。
#4242 ### cx_Oracle 连接参数现代化,废弃的参数已移除
对于 cx_oracle 方言接受的参数以及 URL 字符串进行了一系列现代化处理:
- 废弃的参数
auto_setinputsizes
、allow_twophase
、exclude_setinputsizes
已被移除。 threaded
参数的值,对于 SQLAlchemy 方言一直默认为 True,现在不再默认生成。SQLAlchemy 的Connection
对象本身不被视为线程安全,因此不需要传递此标志。- 将
threaded
传递给create_engine()
本身已被弃用。要将threaded
的值设置为True
,请将其传递给create_engine.connect_args
字典或使用查询字符串,例如oracle+cx_oracle://...?threaded=true
。 - 现在,传递到 URL 查询字符串的所有参数,如果不被特别消耗,都会传递给 cx_Oracle.connect() 函数。其中一些也会被强制转换为 cx_Oracle 常量或布尔值,包括
mode
、purity
、events
和threaded
。 - 与之前一样,所有 cx_Oracle
.connect()
参数都通过create_engine.connect_args
字典接受,文档在这方面是不准确的。
#4369 ### 国家字符数据类型被弱化以支持通用 Unicode,可通过选项重新启用。
默认情况下,Unicode
和 UnicodeText
数据类型现在对应于 Oracle 上的 VARCHAR2
和 CLOB
数据类型,而不是 NVARCHAR2
和 NCLOB
(也称为“国家”字符集类型)。这将在诸如它们在 CREATE TABLE
语句中的呈现方式等行为中看到,以及当使用 Unicode
或 UnicodeText
绑定参数时,不会传递任何类型对象给 setinputsizes()
;cx_Oracle 会原生处理字符串值。这一变化基于 cx_Oracle 的维护者的建议,即 Oracle 中的“国家”数据类型在很大程度上已经过时且性能不佳。它们还会在某些情况下干扰,比如应用于 trunc()
等函数的格式说明符时。
可能需要使用 NVARCHAR2
和相关类型的情况是数据库未使用符合 Unicode 标准的字符集。在这种情况下,可以通过将标志 use_nchar_for_unicode
传递给 create_engine()
来重新启用旧行为。
始终如此,在 DDL 中明确使用NVARCHAR2
和NCLOB
数据类型将继续使用NVARCHAR2
和NCLOB
,包括在处理绑定参数时使用 cx_Oracle 的setinputsizes()
。
在读取方面,在 Python 2 下已添加了 CHAR/VARCHAR/CLOB 结果行的自动 Unicode 转换,以匹配 Python 3 下 cx_Oracle 的行为。为了减轻以前在 Python 2 下 cx_Oracle 方言在这种行为下的性能损失,SQLAlchemy 在 Python 2 下使用了非常高效(当构建了 C 扩展时)的本地 Unicode 处理程序。自动 Unicode 强制转换可以通过将coerce_to_unicode
标志设置为 False 来禁用。该标志现在默认为 True,并适用于结果集中返回的所有不明确为Unicode
或 Oracle 的 NVARCHAR2/NCHAR/NCLOB 数据类型的字符串数据。
cx_Oracle 连接参数现代化,弃用的参数已移除
对 cx_oracle 方言接受的参数以及 URL 字符串进行了一系列现代化改进:
- 弃用的参数
auto_setinputsizes
、allow_twophase
、exclude_setinputsizes
已被移除。 threaded
参数的值,对于 SQLAlchemy 方言始终默认为 True,现在不再默认生成。SQLAlchemy 的Connection
对象本身不被认为是线程安全的,因此不需要传递此标志。- 将
threaded
传递给create_engine()
本身已被弃用。要将threaded
的值设置为True
,请将其传递给create_engine.connect_args
字典或使用查询字符串,例如oracle+cx_oracle://...?threaded=true
。 - 现在,URL 查询字符串中传递的所有参数,如果不被特殊消耗,都会传递给 cx_Oracle.connect()函数。其中一些参数也会被强制转换为 cx_Oracle 常量或布尔值,包括
mode
、purity
、events
和threaded
。 - 与之前一样,所有 cx_Oracle 的
.connect()
参数都可以通过create_engine.connect_args
字典接受,文档在这方面描述不准确。
方言改进和变化 - SQL Server
支持 pyodbc fast_executemany
Pyodbc 最近添加的“fast_executemany”模式,在使用 Microsoft ODBC 驱动程序时可用,现在是 pyodbc / mssql 方言的选项。通过create_engine()
传递:
engine = create_engine( "mssql+pyodbc://scott:tiger@mssql2017:1433/test?driver=ODBC+Driver+13+for+SQL+Server", fast_executemany=True, )
另请参阅
快速执行多模式
#4158 ### 新参数影响 IDENTITY 的起始和增量,使用 Sequence 已被弃用
从 SQL Server 2012 开始,SQL Server 现在支持具有真实CREATE SEQUENCE
语法的序列。在#4235中,SQLAlchemy 将添加对这些的支持,使用Sequence
方式与任何其他方言相同。然而,当前情况是,Sequence
已经在 SQL Server 上重新用途,以影响主键列上IDENTITY
规范的“start”和“increment”参数。为了使过渡向正常序列也可用,使用Sequence
将在整个 1.3 系列中发出弃用警告。为了影响“start”和“increment”,在Column
上使用新的mssql_identity_start
和mssql_identity_increment
参数:
test = Table( "test", metadata_obj, Column( "id", Integer, primary_key=True, mssql_identity_start=100, mssql_identity_increment=10, ), Column("name", String(20)), )
为了在非主键列上发出IDENTITY
,这是一个很少使用但有效的 SQL Server 用例,使用Column.autoincrement
标志,将其设置为True
在目标列上,False
在任何整数主键列上:
test = Table( "test", metadata_obj, Column("id", Integer, primary_key=True, autoincrement=False), Column("number", Integer, autoincrement=True), )
另请参阅
自增行为 / IDENTITY 列
#4235 ### 支持 pyodbc fast_executemany
Pyodbc 最近添加的“fast_executemany”模式,在使用 Microsoft ODBC 驱动程序时可用,现在是 pyodbc / mssql 方言的选项。通过create_engine()
传递:
engine = create_engine( "mssql+pyodbc://scott:tiger@mssql2017:1433/test?driver=ODBC+Driver+13+for+SQL+Server", fast_executemany=True, )
另请参阅
快速执行多模式
新参数影响 IDENTITY 的起始和增量,使用 Sequence 已被弃用
从 SQL Server 2012 开始,SQL Server 现在支持具有真实CREATE SEQUENCE
语法的序列。在#4235中,SQLAlchemy 将使用Sequence
来支持这些,方式与任何其他方言相同。然而,当前情况是,Sequence
已经在 SQL Server 上重新用途,以影响主键列上IDENTITY
规范的“start”和“increment”参数。为了使过渡向正常序列也可用,使用Sequence
将在整个 1.3 系列中发出弃用警告。为了影响“start”和“increment”,请在Column
上使用新的mssql_identity_start
和mssql_identity_increment
参数:
test = Table( "test", metadata_obj, Column( "id", Integer, primary_key=True, mssql_identity_start=100, mssql_identity_increment=10, ), Column("name", String(20)), )
为了在非主键列上发出IDENTITY
,这是一个很少使用但有效的 SQL Server 用例,可以使用Column.autoincrement
标志,在目标列上将其设置为True
,在任何整数主键列上将其设置为False
:
test = Table( "test", metadata_obj, Column("id", Integer, primary_key=True, autoincrement=False), Column("number", Integer, autoincrement=True), )
另请参阅
自动增量行为 / IDENTITY 列
更改了 StatementError 的格式(换行和%s)
对StatementError
的字符串表示引入了两个更改。字符串表示的“detail”和“SQL”部分现在由换行符分隔,并保留了原始 SQL 语句中存在的换行符。目标是提高可读性,同时仍然保持原始错误消息在一行上以便于日志记录。
这意味着以前看起来像这样的错误消息:
sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'id' [SQL: 'select * from reviews\nwhere id = ?'] (Background on this error at: https://sqlalche.me/e/cd3x)
现在看起来像这样:
sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'id' [SQL: select * from reviews where id = ?] (Background on this error at: https://sqlalche.me/e/cd3x)
此更改的主要影响是消费者不能再假设完整的异常消息在单行上,但是从 DBAPI 驱动程序或 SQLAlchemy 内部生成的原始“error”部分仍将在第一行上。