SqlAlchemy 2.0 中文文档(七十五)(4)https://developer.aliyun.com/article/1562372
方言改进和更改 - PostgreSQL
支持 INSERT…ON CONFLICT (DO UPDATE | DO NOTHING)
自 PostgreSQL 9.5 版本起添加的 INSERT
的 ON CONFLICT
子句现在可以使用 PostgreSQL 特定版本的 Insert
对象来支持,通过 sqlalchemy.dialects.postgresql.dml.insert()
。这个 Insert
子类添加了两个新方法 Insert.on_conflict_do_update()
和 Insert.on_conflict_do_nothing()
,实现了 PostgreSQL 9.5 在这个领域支持的完整语法:
from sqlalchemy.dialects.postgresql import insert insert_stmt = insert(my_table).values(id="some_id", data="some data to insert") do_update_stmt = insert_stmt.on_conflict_do_update( index_elements=[my_table.c.id], set_=dict(data="some data to update") ) conn.execute(do_update_stmt)
上述内容将呈现为:
INSERT INTO my_table (id, data) VALUES (:id, :data) ON CONFLICT id DO UPDATE SET data=:data_2
另请参阅
INSERT…ON CONFLICT (Upsert)
#3529 ### ARRAY 和 JSON 类型现在正确指定为“不可哈希”
如 关于“不可哈希”类型的更改,影响 ORM 行的去重 中描述的,ORM 在查询的选择实体混合了完整的 ORM 实体和列表达式时,依赖于能够为列值生成哈希函数。hashable=False
标志现在已正确设置在 PG 的“数据结构”类型上,包括 ARRAY
和 JSON
。JSONB
和 HSTORE
类型已经包含了此标志。对于 ARRAY
,这取决于 ARRAY.as_tuple
标志,但是现在不再需要设置此标志以使数组值出现在组合的 ORM 行中。
另请参阅
关于“不可哈希”类型的更改,影响 ORM 行的去重
从 ARRAY、JSON、HSTORE 的索引访问正确地建立 SQL 类型
#3499 ### 从 ARRAY、JSON、HSTORE 的索引访问正确地建立 SQL 类型
对于所有三种类型 ARRAY
、JSON
和 HSTORE
,通过索引访问返回的表达式的 SQL 类型,例如 col[someindex]
,在所有情况下都应正确。
包括:
- 对于索引访问的
ARRAY
,分配的 SQL 类型将考虑配置的维度数量。一个具有三个维度的ARRAY
将返回一个类型为ARRAY
的 SQL 表达式,维度减少一个。给定类型为ARRAY(Integer, dimensions=3)
的列,现在我们可以执行以下表达式:
int_expr = col[5][6][7] # returns an Integer expression object
- 以前,对于
col[5]
的索引访问将返回一个Integer
类型的表达式,我们无法再对剩余维度进行索引访问,除非使用cast()
或type_coerce()
。 JSON
和JSONB
类型现在与 PostgreSQL 本身对于索引访问的操作一致。这意味着对于JSON
或JSONB
类型的所有索引访问都会返回一个表达式,该表达式本身始终是JSON
或JSONB
本身,除非使用了Comparator.astext
修饰符。这意味着,无论 JSON 结构的索引访问最终指向字符串、列表、数字还是其他 JSON 结构,PostgreSQL 总是将其视为 JSON 本身,除非明确进行了不同的类型转换。与ARRAY
类型类似,现在可以轻松地生成具有多层索引访问的 JSON 表达式:
json_expr = json_col["key1"]["attr1"][5]
- 通过
HSTORE
的索引访问返回的“文本”类型,以及与Comparator.astext
修饰符一起返回的JSON
和JSONB
的“文本”类型现在是可配置的;在这两种情况下,默认为TextClause
,但可以使用JSON.astext_type
或HSTORE.text_type
参数将其设置为用户定义的类型。
另请参阅
JSON cast() 操作现在需要显式调用 .astext
#3499 #3487 ### JSON cast() 操作现在需要显式调用 .astext
作为从数组、JSON、HSTORE 的索引访问中正确建立 SQL 类型的更改的一部分,ColumnElement.cast()
操作符在 JSON
和 JSONB
上不再隐式调用 Comparator.astext
修饰符;PostgreSQL 的 JSON/JSONB 类型支持彼此之间的 CAST 操作,无需“astext”方面。
这意味着在大多数情况下,一个应用程序正在执行这个操作:
expr = json_col["somekey"].cast(Integer)
现在需要更改为:
expr = json_col["somekey"].astext.cast(Integer) ```### 带有 ENUM 的数组现在将发出 ENUM 的 CREATE TYPE 表定义如下将会按预期发出 CREATE TYPE: ```py enum = Enum( "manager", "place_admin", "carwash_admin", "parking_admin", "service_admin", "tire_admin", "mechanic", "carwasher", "tire_mechanic", name="work_place_roles", ) class WorkPlacement(Base): __tablename__ = "work_placement" id = Column(Integer, primary_key=True) roles = Column(ARRAY(enum)) e = create_engine("postgresql://scott:tiger@localhost/test", echo=True) Base.metadata.create_all(e)
发出:
CREATE TYPE work_place_roles AS ENUM ( 'manager', 'place_admin', 'carwash_admin', 'parking_admin', 'service_admin', 'tire_admin', 'mechanic', 'carwasher', 'tire_mechanic') CREATE TABLE work_placement ( id SERIAL NOT NULL, roles work_place_roles[], PRIMARY KEY (id) )
检查约束现在反映
PostgreSQL 方言现在支持检索 CHECK 约束,方法包括 Inspector.get_check_constraints()
和 Table
反射中的 Table.constraints
集合。
“Plain” 和 “Materialized” 视图可以分别检查
新参数 PGInspector.get_view_names.include
允许指定应返回哪些视图子类型:
from sqlalchemy import inspect insp = inspect(engine) plain_views = insp.get_view_names(include="plain") all_views = insp.get_view_names(include=("plain", "materialized"))
Index 添加 tablespace 选项
Index
对象现在接受参数 postgresql_tablespace
,以指定 TABLESPACE,与 Table
对象所接受的方式相同。
另请参见
Index Storage Parameters
PyGreSQL 的支持
PyGreSQL DBAPI 现在得到支持。
“postgres” 模块已被移除
sqlalchemy.dialects.postgres
模块,长期弃用,已被移除;多年来一直发出警告,项目应调用 sqlalchemy.dialects.postgresql
。形式为 postgres://
的 Engine URLs 仍将继续运行。
支持 FOR UPDATE SKIP LOCKED / FOR NO KEY UPDATE / FOR KEY SHARE
新参数 GenerativeSelect.with_for_update.skip_locked
和 GenerativeSelect.with_for_update.key_share
��� Core 和 ORM 中都应用于 PostgreSQL 后端的 “SELECT…FOR UPDATE” 或 “SELECT…FOR SHARE” 查询的修改:
- SELECT FOR NO KEY UPDATE:
stmt = select([table]).with_for_update(key_share=True)
- SELECT FOR UPDATE SKIP LOCKED:
stmt = select([table]).with_for_update(skip_locked=True)
- SELECT FOR KEY SHARE:
stmt = select([table]).with_for_update(read=True, key_share=True)
支持 INSERT…ON CONFLICT (DO UPDATE | DO NOTHING)
INSERT
的 ON CONFLICT
子句,自 PostgreSQL 版本 9.5 起添加,现在可使用 PostgreSQL 特定版本的 Insert
对象支持,通过 sqlalchemy.dialects.postgresql.dml.insert()
。这个 Insert
子类添加了两个新方法 Insert.on_conflict_do_update()
和 Insert.on_conflict_do_nothing()
,实现了 PostgreSQL 9.5 在这个领域支持的完整语法:
from sqlalchemy.dialects.postgresql import insert insert_stmt = insert(my_table).values(id="some_id", data="some data to insert") do_update_stmt = insert_stmt.on_conflict_do_update( index_elements=[my_table.c.id], set_=dict(data="some data to update") ) conn.execute(do_update_stmt)
上述内容将渲染为:
INSERT INTO my_table (id, data) VALUES (:id, :data) ON CONFLICT id DO UPDATE SET data=:data_2
另请参见
INSERT…ON CONFLICT (Upsert)
ARRAY 和 JSON 类型现在正确指定“不可哈希”
如关于“不可哈希”类型的变更,影响了 ORM 行的去重所述,ORM 在查询的选定实体中混合全 ORM 实体与列表达式时,依赖于能够为列值产生哈希函数。现在,hashable=False
标志已正确设置在所有 PG 的“数据结构”类型上,包括ARRAY
和JSON
。JSONB
和HSTORE
类型已经包括了这个标志。对于ARRAY
,这取决于ARRAY.as_tuple
标志,然而,现在应该不再需要设置这个标志,以便在组合的 ORM 行中具有数组值。
另请参见
关于“不可哈希”类型的变更,影响了 ORM 行的去重
从 ARRAY、JSON、HSTORE 的索引访问正确建立 SQL 类型
从 ARRAY、JSON、HSTORE 的索引访问正确建立 SQL 类型
对于ARRAY
、JSON
和HSTORE
三者,通过索引访问返回的表达式所分配的 SQL 类型,例如 col[someindex]
,在所有情况下都应该是正确的。
这包括:
- 对于
ARRAY
的索引访问所分配的 SQL 类型将考虑到配置的维度数量。一个具有三个维度的ARRAY
将返回一个维度少一的ARRAY
的 SQL 表达式类型。给定一个类型为ARRAY(Integer, dimensions=3)
的列,我们现在可以执行这个表达式:
int_expr = col[5][6][7] # returns an Integer expression object
- 以前,对于
col[5]
的索引访问将返回一个Integer
类型的表达式,我们无法再对剩余维度进行索引访问,除非使用cast()
或type_coerce()
。 JSON
和JSONB
类型现在与 PostgreSQL 本身对于索引访问的操作一致。这意味着对于JSON
或JSONB
类型的所有索引访问都会返回一个表达式,该表达式本身始终是JSON
或JSONB
本身,除非使用了Comparator.astext
修饰符。这意味着,无论 JSON 结构的索引访问最终指向字符串、列表、数字还是其他 JSON 结构,PostgreSQL 总是将其视为 JSON 本身,除非明确进行了不同的类型转换。与ARRAY
类型类似,现在可以轻松地生成具有多层索引访问的 JSON 表达式:
json_expr = json_col["key1"]["attr1"][5]
- 通过对
HSTORE
的索引访问返回的“文本”类型,以及通过对JSON
和JSONB
的索引访问返回的“文本”类型,再结合Comparator.astext
修饰符,现在是可配置的;在这两种情况下,默认为TextClause
,但可以使用JSON.astext_type
或HSTORE.text_type
参数将其设置为用户定义的类型。
另请参阅
JSON cast() 操作现在需要显式调用 .astext
JSON cast() 操作现在需要显式调用 .astext
作为 从数组、JSON、HSTORE 的索引访问正确建立 SQL 类型的更改 的一部分,ColumnElement.cast()
操作在 JSON
和 JSONB
上不再隐式调用 Comparator.astext
修饰符;PostgreSQL 的 JSON/JSONB 类型支持彼此之间的 CAST 操作,无需 “astext” 方面。
这意味着在大多数情况下,一个应用程序如果在做这个操作:
expr = json_col["somekey"].cast(Integer)
现在需要更改为:
expr = json_col["somekey"].astext.cast(Integer)
带有 ENUM 的数组现在会发出 CREATE TYPE 用于 ENUM
类似以下的表定义现在会按预期发出 CREATE TYPE:
enum = Enum( "manager", "place_admin", "carwash_admin", "parking_admin", "service_admin", "tire_admin", "mechanic", "carwasher", "tire_mechanic", name="work_place_roles", ) class WorkPlacement(Base): __tablename__ = "work_placement" id = Column(Integer, primary_key=True) roles = Column(ARRAY(enum)) e = create_engine("postgresql://scott:tiger@localhost/test", echo=True) Base.metadata.create_all(e)
发出:
CREATE TYPE work_place_roles AS ENUM ( 'manager', 'place_admin', 'carwash_admin', 'parking_admin', 'service_admin', 'tire_admin', 'mechanic', 'carwasher', 'tire_mechanic') CREATE TABLE work_placement ( id SERIAL NOT NULL, roles work_place_roles[], PRIMARY KEY (id) )
检查约束现在反映
PostgreSQL 方言现在支持反射 CHECK 约束,方法包括 Inspector.get_check_constraints()
以及 Table
反射中的 Table.constraints
集合。
可以单独检查“普通”和“物化”视图
新参数 PGInspector.get_view_names.include
允许指定应返回哪些视图子类型:
from sqlalchemy import inspect insp = inspect(engine) plain_views = insp.get_view_names(include="plain") all_views = insp.get_view_names(include=("plain", "materialized"))
向 Index 添加 tablespace 选项
Index
对象现在接受参数 postgresql_tablespace
,以指定 TABLESPACE,与 Table
对象接受的方式相同。
参见
索引存储参数
对 PyGreSQL 的支持
PyGreSQL DBAPI 现在受支持。
“postgres” 模块已移除
长期弃用的 sqlalchemy.dialects.postgres
模块已被移除;多年来一直发出警告,项目应该调用 sqlalchemy.dialects.postgresql
。形式为 postgres://
的 Engine URLs 仍将继续运行。
支持 FOR UPDATE SKIP LOCKED / FOR NO KEY UPDATE / FOR KEY SHARE
Core 和 ORM 中的新参数 GenerativeSelect.with_for_update.skip_locked
和 GenerativeSelect.with_for_update.key_share
在 PostgreSQL 后端上对 “SELECT…FOR UPDATE” 或 “SELECT…FOR SHARE” 查询应用修改:
- SELECT FOR NO KEY UPDATE:
stmt = select([table]).with_for_update(key_share=True)
- SELECT FOR UPDATE SKIP LOCKED:
stmt = select([table]).with_for_update(skip_locked=True)
- SELECT FOR KEY SHARE:
stmt = select([table]).with_for_update(read=True, key_share=True)
方言改进和更改 - MySQL
MySQL JSON 支持
新类型 JSON
已添加到 MySQL 方言,支持 MySQL 5.7 新增的 JSON 类型。该类型提供 JSON 的持久性以及内部使用 JSON_EXTRACT
函数进行基本索引访问。通过使用 MySQL 和 PostgreSQL 共同的 JSON
数据类型,可以实现跨 MySQL 和 PostgreSQL 的可索引 JSON 列。
参见
核心中添加的 JSON 支持
#3547 ### 增加了对 AUTOCOMMIT “隔离级别”的支持
MySQL 方言现在接受值“AUTOCOMMIT”作为 create_engine.isolation_level
和 Connection.execution_options.isolation_level
参数:
connection = engine.connect() connection = connection.execution_options(isolation_level="AUTOCOMMIT")
隔离级别利用大多数 MySQL DBAPI 提供的各种“autocommit”属性。
#3332 ### 不再为具有 AUTO_INCREMENT 的复合主键生成隐式 KEY
MySQL 方言的行为是,如果 InnoDB 表上的复合主键中的一个列具有 AUTO_INCREMENT 但不是第一列,例如:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True, autoincrement=False), Column("y", Integer, primary_key=True, autoincrement=True), mysql_engine="InnoDB", )
会生成如下的 DDL:
CREATE TABLE some_table ( x INTEGER NOT NULL, y INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (x, y), KEY idx_autoinc_y (y) )ENGINE=InnoDB
请注意上述带有自动生成名称的“KEY”;这是多年前针对 AUTO_INCREMENT 在 InnoDB 上否则会失败的问题而进入方言的变更。
这种解决方法已被移除,并替换为更好的系统,即在主键中仅将 AUTO_INCREMENT 列 放在第一位:
CREATE TABLE some_table ( x INTEGER NOT NULL, y INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (y, x) )ENGINE=InnoDB
要明确控制主键列的排序,请显式使用 PrimaryKeyConstraint
构造(1.1.0b2)(以及根据 MySQL 要求的自动增量列的 KEY),例如:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True), Column("y", Integer, primary_key=True, autoincrement=True), PrimaryKeyConstraint("x", "y"), UniqueConstraint("y"), mysql_engine="InnoDB", )
除了变更 不再为复合主键列隐式启用 .autoincrement 指令 外,现在更容易指定具有或不具有自动增量的复合主键;Column.autoincrement
现在默认为值 "auto"
,不再需要 autoincrement=False
指令:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True), Column("y", Integer, primary_key=True, autoincrement=True), mysql_engine="InnoDB", ) ```### MySQL JSON 支持 MySQL 方言现在支持新增于 MySQL 5.7 的 JSON 类型,为此添加了一种新类型 `JSON`。该类型提供了 JSON 的持久性以及内部使用 `JSON_EXTRACT` 函数进行基本索引访问。通过使用在 MySQL 和 PostgreSQL 中通用的 `JSON` 数据类型,可以实现跨 MySQL 和 PostgreSQL 的可索引 JSON 列。 另请参见 核心中添加的 JSON 支持 [#3547](https://www.sqlalchemy.org/trac/ticket/3547) ### 增加了对 AUTOCOMMIT “隔离级别”的支持 MySQL 方言现在接受值“AUTOCOMMIT”作为`create_engine.isolation_level`和`Connection.execution_options.isolation_level`参数: ```py connection = engine.connect() connection = connection.execution_options(isolation_level="AUTOCOMMIT")
隔离级别利用大多数 MySQL DBAPI 提供的各种“autocommit”属性。
不再为具有 AUTO_INCREMENT 的复合主键生成隐式 KEY
MySQL 方言的行为是,如果 InnoDB 表上的复合主键中的一个列具有 AUTO_INCREMENT 且不是第一列,例如:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True, autoincrement=False), Column("y", Integer, primary_key=True, autoincrement=True), mysql_engine="InnoDB", )
将生成以下 DDL:
CREATE TABLE some_table ( x INTEGER NOT NULL, y INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (x, y), KEY idx_autoinc_y (y) )ENGINE=InnoDB
请注意上述带有自动生成名称的“KEY”;这是多年前为了解决 AUTO_INCREMENT 在 InnoDB 上否则会失败的问题而引入的方言变化。
这个解决方法已被移除,并用更好的系统替代,即在主键中首先声明 AUTO_INCREMENT 列:
CREATE TABLE some_table ( x INTEGER NOT NULL, y INTEGER NOT NULL AUTO_INCREMENT, PRIMARY KEY (y, x) )ENGINE=InnoDB
为了明确控制主键列的顺序,请显式使用PrimaryKeyConstraint
构造(1.1.0b2)(以及 MySQL 所需的自动增量列的 KEY),例如:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True), Column("y", Integer, primary_key=True, autoincrement=True), PrimaryKeyConstraint("x", "y"), UniqueConstraint("y"), mysql_engine="InnoDB", )
伴随着变化.autoincrement 指令不再隐式启用复合主键列,现在更容易指定具有或不具有自动增量的复合主键;Column.autoincrement
现在默认为值"auto"
,不再需要autoincrement=False
指令:
t = Table( "some_table", metadata, Column("x", Integer, primary_key=True), Column("y", Integer, primary_key=True, autoincrement=True), mysql_engine="InnoDB", )
方言改进和变化 - SQLite
SQLite 版本 3.7.16 解决的右嵌套连接问题
在 0.9 版本中,由 许多 JOIN 和 LEFT OUTER JOIN 表达式将不再被包装在 (SELECT * FROM …) AS ANON_1 中 引入的功能经历了大量努力,以支持在 SQLite 上重写连接以始终使用子查询以实现“右嵌套连接”效果,因为多年来 SQLite 并不支持这种语法。具有讽刺意味的是,在该迁移说明中指出的 SQLite 版本 3.7.15.2,实际上是 SQLite 最后一个具有这种限制的版本!下一个版本是 3.7.16,支持右嵌套连接被悄悄地添加了进去。在 1.1 版本中,已经完成了识别特定 SQLite 版本和源提交的工作,这个变化的解决方案现在在 SQLite 报告版本 3.7.16 或更高版本时被取消。
#3634 ### 取消 SQLite 版本 3.10.0 中的带点列名变通方法
SQLite 方言长期以来一直存在一个问题的变通方法,即数据库驱动程序在某些 SQL 结果集中没有报告正确的列名,特别是在使用 UNION 时。这个变通方法在 带点的列名 中有详细说明,并要求 SQLAlchemy 假定任何带有点的列名实际上是通过这种错误行为传递的 tablename.columnname
组合,可以通过 sqlite_raw_colnames
执行选项关闭这个选项。
截至 SQLite 版本 3.10.0,UNION 和其他查询中的错误已经修复;就像 SQLite 版本 3.7.16 中取消右嵌套连接的变通方法 中描述的变化一样,SQLite 的变更日志只将其神秘地标识为“为 sqlite3_module.xBestIndex 方法添加了 colUsed 字段”,但是 SQLAlchemy 对这些带点的列名的转换在这个版本中不再需要,因此当检测到版本 3.10.0 或更高版本时会关闭这个功能。
总的来说,截至 1.0 系列,SQLAlchemy 的 ResultProxy
在为 Core 和 ORM SQL 结构提供结果时,对列名的依赖要少得多,因此这个问题的重要性在任何情况下都已经降低了。
#3633 ### 改进对远程模式的支持
SQLite 方言现在实现了 Inspector.get_schema_names()
,并且对于从远程模式创建和反映的表和索引提供了改进的支持,在 SQLite 中,远程模式是通过 ATTACH
语句分配名称的数据库;先前,CREATE INDEX
DDL 对于模式绑定表不起作用,并且 Inspector.get_foreign_keys()
方法现在将在结果中指示给定的模式。不支持跨模式外键。### 主键约束名称的反射
SQLite 后端现在利用 SQLite 的“sqlite_master”视图来提取表的原始 DDL 中主键约束的名称,这与 SQLAlchemy 的最新版本中用于提取外键约束的方式相同。
检查约束现在反映
SQLite 方言现在支持检查约束的反射,包括在方法 Inspector.get_check_constraints()
内以及在 Table
反映中的 Table.constraints
集合内。
ON DELETE 和 ON UPDATE 外键短语现在反映
Inspector
现在将包括来自 SQLite 方言的外键约束的 ON DELETE 和 ON UPDATE 短语,并且作为 Table
的一部分反映的 ForeignKeyConstraint
对象也将指示这些短语。
右嵌套连接解决方案针对 SQLite 版本 3.7.16 解除
在版本 0.9 中,由 许多 JOIN 和 LEFT OUTER JOIN 表达式将不再被包裹在 (SELECT * FROM …) AS ANON_1 中 引入的功能经历了大量努力,以支持在 SQLite 上重写连接以始终使用子查询以实现“右嵌套连接”效果,因为 SQLite 多年来一直不支持这种语法。具有讽刺意味的是,在迁移说明中指出的 SQLite 版本 3.7.15.2 实际上是 SQLite 最后一个具有这种限制的版本!下一个发布版本是 3.7.16,支持右嵌套连接被悄悄地添加了进去。在 1.1 中,已经完成了识别特定 SQLite 版本和源提交的工作,其中进行了这一更改(SQLite 的更改日志用神秘的短语“增强查询优化器以利用传递连接约束”来指称,没有链接到任何问题编号、更改编号或进一步解释),并且当 DBAPI 报告版本 3.7.16 或更高版本生效时,此更改中存在的变通方法现在已经被取消了。
取消 SQLite 版本 3.10.0 中的带点列名变通方法
SQLite 方言长期以来一直有一个解决方案,用于解决数据库驱动程序在某些 SQL 结果集中未报告正确列名的问题,特别是在使用 UNION 时。这个解决方案在 带点列名 中有详细说明,并要求 SQLAlchemy 假定任何带有点的列名实际上是通过这种错误行为传递的 tablename.columnname
组合,可以通过 sqlite_raw_colnames
执行选项关闭这个选项。
截至 SQLite 版本 3.10.0,UNION 和其他查询中的错误已经修复;就像 SQLite 版本 3.7.16 中取消右嵌套连接变通方法 中描述的更改一样,SQLite 的更改日志只将其神秘地标识为“为 sqlite3_module.xBestIndex 方法添加了 colUsed 字段”,然而 SQLAlchemy 对这些带点的列名的转换在此版本中不再需要,因此当检测到版本 3.10.0 或更高版本时,将其关闭。
总的来说,在 1.0 系列中的 SQLAlchemy ResultProxy
在为 Core 和 ORM SQL 结构提供结果时,对列名的依赖要少得多,因此这个问题的重要性在任何情况下已经降低了。
改进对远程模式的支持
SQLite 方言现在实现了Inspector.get_schema_names()
,并且对于从远程模式创建和反映的表和索引提供了改进的支持,在 SQLite 中,远程模式是通过ATTACH
语句分配名称的数据库;以前,CREATE INDEX
DDL 对于绑定模式表的情况无法正确工作,而Inspector.get_foreign_keys()
方法现在将在结果中指示给定的模式。不支持跨模式外键。
反映主键约束的名称
SQLite 后端现在利用 SQLite 的“sqlite_master”视图,以从原始 DDL 中提取表的主键约束的名称,就像最近 SQLAlchemy 版本中为外键约束所实现的方式一样。
检查约束现在反映
SQLite 方言现在支持在方法Inspector.get_check_constraints()
以及在Table
反映中的Table.constraints
集合中反映 CHECK 约束。
ON DELETE 和 ON UPDATE 外键短语现在反映
Inspector
现在将包括 SQLite 方言上外键约束的 ON DELETE 和 ON UPDATE 短语,并且作为Table
的一部分反映的ForeignKeyConstraint
对象也将指示这些短语。
方言改进和更改 - SQL Server
为 SQL Server 添加了事务隔离级别支持
所有 SQL Server 方言都支持通过create_engine.isolation_level
和Connection.execution_options.isolation_level
参数设置事务隔离级别。四个标准级别以及SNAPSHOT
都受支持:
engine = create_engine( "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ" )
另请参见
事务隔离级别
#3534 ### 反射时字符串/可变长度类型不再明确表示“max”
当反射诸如String
、TextClause
等包含长度的类型时,在 SQL Server 下,“无长度”类型将复制“length”参数作为值"max"
:
>>> from sqlalchemy import create_engine, inspect >>> engine = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True) >>> engine.execute("create table s (x varchar(max), y varbinary(max))") >>> insp = inspect(engine) >>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> max <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> max
基本类型中的“length”参数预期只能是整数值或None
;None
表示无限长度,SQL Server 方言将其解释为“max”。修复方法是将这些长度输出为None
,以便类型对象在非 SQL Server 上下文中正常工作:
>>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> None <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> None
可能一直依赖于将“length”值直接与字符串“max”进行比较的应用程序应该考虑将值设为None
表示相同的含义。
支持在主键上使用“非聚集”以允许在其他地方进行聚集
UniqueConstraint
、PrimaryKeyConstraint
、Index
上可用的 mssql_clustered
标志现在默认为 None
,可以设置为 False,这将特别为主键渲染 NONCLUSTERED
关键字,允许使用不同的索引作为“聚集”。
另请参见
聚集索引支持
legacy_schema_aliasing
标志现在设置为 False
SQLAlchemy 1.0.5 引入了 legacy_schema_aliasing
标志到 MSSQL 方言,允许关闭所谓的“传统模式”别名。这种别名尝试将模式限定的表转换为别名;给定一个表如下:
account_table = Table( "account", metadata, Column("id", Integer, primary_key=True), Column("info", String(100)), schema="customer_schema", )
传统行为模式将尝试将模式限定的表名转换为别名:
>>> eng = create_engine("mssql+pymssql://mydsn", legacy_schema_aliasing=True) >>> print(account_table.select().compile(eng)) SELECT account_1.id, account_1.info FROM customer_schema.account AS account_1
然而,已经证明这种别名是不必要的,在许多情况下会产生不正确的 SQL。
在 SQLAlchemy 1.1 中,legacy_schema_aliasing
标志现在默认为 False,禁用此行为模式,并允许 MSSQL 方言以模式限定的表正常运行。对于可能依赖此行为的应用程序,请将标志设置回 True。
#3434 ### 为 SQL Server 添加了事务隔离级别支持
所有 SQL Server 方言都支持通过create_engine.isolation_level
和Connection.execution_options.isolation_level
参数设置事务隔离级别。四个标准级别都受支持,以及SNAPSHOT
:
engine = create_engine( "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ" )
另请参阅
事务隔离级别
字符串/可变长度类型不再在反射时显式表示“max”
当反射像String
、TextClause
等包含长度的类型时,SQL Server 下的“无长度”类型会将“长度”参数复制为值"max"
:
>>> from sqlalchemy import create_engine, inspect >>> engine = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True) >>> engine.execute("create table s (x varchar(max), y varbinary(max))") >>> insp = inspect(engine) >>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> max <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> max
基本类型中的“长度”参数预期只是一个整数值或仅为 None;None 表示无界长度,而 SQL Server 方言将其解释为“max”。因此修复这些长度为 None,以便类型对象在非 SQL Server 上下文中工作:
>>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> None <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> None
可能已经依赖将“长度”值直接与字符串“max”进行比较的应用程序应考虑将值None
视为相同的含义。
支持在其他地方集群化以允许主键上的“非聚集”
现在UniqueConstraint
、PrimaryKeyConstraint
、Index
上可用的mssql_clustered
标志默认为None
,并且可以设置为 False,这将在特定情况下渲染 NONCLUSTERED 关键字用于主键,允许使用不同的索引作为“集群化”。
另请参阅
集群索引支持
legacy_schema_aliasing
标志现在设置为 False
SQLAlchemy 1.0.5 引入了legacy_schema_aliasing
标志到 MSSQL 方言中,允许所谓的“遗留模式”别名化被关闭。这种别名化试图将架构限定的表转换为别名;给定这样一个表:
account_table = Table( "account", metadata, Column("id", Integer, primary_key=True), Column("info", String(100)), schema="customer_schema", )
行为的遗留模式将尝试将架构限定的表名转换为别名:
>>> eng = create_engine("mssql+pymssql://mydsn", legacy_schema_aliasing=True) >>> print(account_table.select().compile(eng)) SELECT account_1.id, account_1.info FROM customer_schema.account AS account_1
然而,这种别名化已被证明是不必要的,并且在许多情况下会产生不正确的 SQL。
在 SQLAlchemy 1.1 中,legacy_schema_aliasing
标志现在默认为 False,禁用此行为模式,允许 MSSQL 方言与模式限定的表正常运行。对于可能依赖此行为的应用程序,请将标志设置回 True。
方言改进和变更 - Oracle
支持 SKIP LOCKED
在 Core 和 ORM 中的新参数GenerativeSelect.with_for_update.skip_locked
将为“SELECT…FOR UPDATE”或“SELECT… FOR SHARE”查询生成“SKIP LOCKED”后缀。
支持 SKIP LOCKED
在 Core 和 ORM 中的新参数GenerativeSelect.with_for_update.skip_locked
将为“SELECT…FOR UPDATE”或“SELECT… FOR SHARE”查询生成“SKIP LOCKED”后缀。
SQLite 版本 3.10.0 中的带点列名变通方法
SQLite 方言长期以来一直有一个解决方案,用于解决数据库驱动程序在某些 SQL 结果集中未报告正确列名的问题,特别是在使用 UNION 时。这个解决方案在 带点列名 中有详细说明,并要求 SQLAlchemy 假定任何带有点的列名实际上是通过这种错误行为传递的 tablename.columnname
组合,可以通过 sqlite_raw_colnames
执行选项关闭这个选项。
截至 SQLite 版本 3.10.0,UNION 和其他查询中的错误已经修复;就像 SQLite 版本 3.7.16 中取消右嵌套连接变通方法 中描述的更改一样,SQLite 的更改日志只将其神秘地标识为“为 sqlite3_module.xBestIndex 方法添加了 colUsed 字段”,然而 SQLAlchemy 对这些带点的列名的转换在此版本中不再需要,因此当检测到版本 3.10.0 或更高版本时,将其关闭。
总的来说,在 1.0 系列中的 SQLAlchemy ResultProxy
在为 Core 和 ORM SQL 结构提供结果时,对列名的依赖要少得多,因此这个问题的重要性在任何情况下已经降低了。
改进对远程模式的支持
SQLite 方言现在实现了Inspector.get_schema_names()
,并且对于从远程模式创建和反映的表和索引提供了改进的支持,在 SQLite 中,远程模式是通过ATTACH
语句分配名称的数据库;以前,CREATE INDEX
DDL 对于绑定模式表的情况无法正确工作,而Inspector.get_foreign_keys()
方法现在将在结果中指示给定的模式。不支持跨模式外键。
反映主键约束的名称
SQLite 后端现在利用 SQLite 的“sqlite_master”视图,以从原始 DDL 中提取表的主键约束的名称,就像最近 SQLAlchemy 版本中为外键约束所实现的方式一样。
检查约束现在反映
SQLite 方言现在支持在方法Inspector.get_check_constraints()
以及在Table
反映中的Table.constraints
集合中反映 CHECK 约束。
ON DELETE 和 ON UPDATE 外键短语现在反映
Inspector
现在将包括 SQLite 方言上外键约束的 ON DELETE 和 ON UPDATE 短语,并且作为Table
的一部分反映的ForeignKeyConstraint
对象也将指示这些短语。
方言改进和更改 - SQL Server
为 SQL Server 添加了事务隔离级别支持
所有 SQL Server 方言都支持通过create_engine.isolation_level
和Connection.execution_options.isolation_level
参数设置事务隔离级别。四个标准级别以及SNAPSHOT
都受支持:
engine = create_engine( "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ" )
另请参见
事务隔离级别
#3534 ### 反射时字符串/可变长度类型不再明确表示“max”
当反射诸如String
、TextClause
等包含长度的类型时,在 SQL Server 下,“无长度”类型将复制“length”参数作为值"max"
:
>>> from sqlalchemy import create_engine, inspect >>> engine = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True) >>> engine.execute("create table s (x varchar(max), y varbinary(max))") >>> insp = inspect(engine) >>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> max <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> max
基本类型中的“length”参数预期只能是整数值或None
;None
表示无限长度,SQL Server 方言将其解释为“max”。修复方法是将这些长度输出为None
,以便类型对象在非 SQL Server 上下文中正常工作:
>>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> None <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> None
可能一直依赖于将“length”值直接与字符串“max”进行比较的应用程序应该考虑将值设为None
表示相同的含义。
支持在主键上使用“非聚集”以允许在其他地方进行聚集
UniqueConstraint
、PrimaryKeyConstraint
、Index
上可用的 mssql_clustered
标志现在默认为 None
,可以设置为 False,这将特别为主键渲染 NONCLUSTERED
关键字,允许使用不同的索引作为“聚集”。
另请参见
聚集索引支持
legacy_schema_aliasing
标志现在设置为 False
SQLAlchemy 1.0.5 引入了 legacy_schema_aliasing
标志到 MSSQL 方言,允许关闭所谓的“传统模式”别名。这种别名尝试将模式限定的表转换为别名;给定一个表如下:
account_table = Table( "account", metadata, Column("id", Integer, primary_key=True), Column("info", String(100)), schema="customer_schema", )
传统行为模式将尝试将模式限定的表名转换为别名:
>>> eng = create_engine("mssql+pymssql://mydsn", legacy_schema_aliasing=True) >>> print(account_table.select().compile(eng)) SELECT account_1.id, account_1.info FROM customer_schema.account AS account_1
然而,已经证明这种别名是不必要的,在许多情况下会产生不正确的 SQL。
在 SQLAlchemy 1.1 中,legacy_schema_aliasing
标志现在默认为 False,禁用此行为模式,并允许 MSSQL 方言以模式限定的表正常运行。对于可能依赖此行为的应用程序,请将标志设置回 True。
#3434 ### 为 SQL Server 添加了事务隔离级别支持
所有 SQL Server 方言都支持通过create_engine.isolation_level
和Connection.execution_options.isolation_level
参数设置事务隔离级别。四个标准级别都受支持,以及SNAPSHOT
:
engine = create_engine( "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ" )
另请参阅
事务隔离级别
字符串/可变长度类型不再在反射时显式表示“max”
当反射像String
、TextClause
等包含长度的类型时,SQL Server 下的“无长度”类型会将“长度”参数复制为值"max"
:
>>> from sqlalchemy import create_engine, inspect >>> engine = create_engine("mssql+pyodbc://scott:tiger@ms_2008", echo=True) >>> engine.execute("create table s (x varchar(max), y varbinary(max))") >>> insp = inspect(engine) >>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> max <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> max
基本类型中的“长度”参数预期只是一个整数值或仅为 None;None 表示无界长度,而 SQL Server 方言将其解释为“max”。因此修复这些长度为 None,以便类型对象在非 SQL Server 上下文中工作:
>>> for col in insp.get_columns("s"): ... print(col["type"].__class__, col["type"].length) <class 'sqlalchemy.sql.sqltypes.VARCHAR'> None <class 'sqlalchemy.dialects.mssql.base.VARBINARY'> None
可能已经依赖将“长度”值直接与字符串“max”进行比较的应用程序应考虑将值None
视为相同的含义。
支持在其他地方集群化以允许主键上的“非聚集”
现在UniqueConstraint
、PrimaryKeyConstraint
、Index
上可用的mssql_clustered
标志默认为None
,并且可以设置为 False,这将在特定情况下渲染 NONCLUSTERED 关键字用于主键,允许使用不同的索引作为“集群化”。
另请参阅
集群索引支持
legacy_schema_aliasing
标志现在设置为 False
SQLAlchemy 1.0.5 引入了legacy_schema_aliasing
标志到 MSSQL 方言中,允许所谓的“遗留模式”别名化被关闭。这种别名化试图将架构限定的表转换为别名;给定这样一个表:
account_table = Table( "account", metadata, Column("id", Integer, primary_key=True), Column("info", String(100)), schema="customer_schema", )
行为的遗留模式将尝试将架构限定的表名转换为别名:
>>> eng = create_engine("mssql+pymssql://mydsn", legacy_schema_aliasing=True) >>> print(account_table.select().compile(eng)) SELECT account_1.id, account_1.info FROM customer_schema.account AS account_1
然而,这种别名化已被证明是不必要的,并且在许多情况下会产生不正确的 SQL。
在 SQLAlchemy 1.1 中,legacy_schema_aliasing
标志现在默认为 False,禁用此行为模式,允许 MSSQL 方言与模式限定的表正常运行。对于可能依赖此行为的应用程序,请将标志设置回 True。
方言改进和变更 - Oracle
支持 SKIP LOCKED
在 Core 和 ORM 中的新参数GenerativeSelect.with_for_update.skip_locked
将为“SELECT…FOR UPDATE”或“SELECT… FOR SHARE”查询生成“SKIP LOCKED”后缀。
支持 SKIP LOCKED
在 Core 和 ORM 中的新参数GenerativeSelect.with_for_update.skip_locked
将为“SELECT…FOR UPDATE”或“SELECT… FOR SHARE”查询生成“SKIP LOCKED”后缀。