SqlAlchemy 2.0 中文文档(七十五)(5)

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

SqlAlchemy 2.0 中文文档(七十五)(4)https://developer.aliyun.com/article/1562372


方言改进和更改 - PostgreSQL

支持 INSERT…ON CONFLICT (DO UPDATE | DO NOTHING)

自 PostgreSQL 9.5 版本起添加的 INSERTON 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 的“数据结构”类型上,包括 ARRAYJSONJSONBHSTORE 类型已经包含了此标志。对于 ARRAY,这取决于 ARRAY.as_tuple 标志,但是现在不再需要设置此标志以使数组值出现在组合的 ORM 行中。

另请参阅

关于“不可哈希”类型的更改,影响 ORM 行的去重

从 ARRAY、JSON、HSTORE 的索引访问正确地建立 SQL 类型

#3499 ### 从 ARRAY、JSON、HSTORE 的索引访问正确地建立 SQL 类型

对于所有三种类型 ARRAYJSONHSTORE,通过索引访问返回的表达式的 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()
  • JSONJSONB 类型现在与 PostgreSQL 本身对于索引访问的操作一致。这意味着对于 JSONJSONB 类型的所有索引访问都会返回一个表达式,该表达式本身始终JSONJSONB 本身,除非使用了 Comparator.astext 修饰符。这意味着,无论 JSON 结构的索引访问最终指向字符串、列表、数字还是其他 JSON 结构,PostgreSQL 总是将其视为 JSON 本身,除非明确进行了不同的类型转换。与 ARRAY 类型类似,现在可以轻松地生成具有多层索引访问的 JSON 表达式:
json_expr = json_col["key1"]["attr1"][5]
  • 通过HSTORE 的索引访问返回的“文本”类型,以及与Comparator.astext 修饰符一起返回的JSONJSONB 的“文本”类型现在是可配置的;在这两种情况下,默认为 TextClause,但可以使用 JSON.astext_typeHSTORE.text_type 参数将其设置为用户定义的类型。

另请参阅

JSON cast() 操作现在需要显式调用 .astext

#3499 #3487 ### JSON cast() 操作现在需要显式调用 .astext

作为从数组、JSON、HSTORE 的索引访问中正确建立 SQL 类型的更改的一部分,ColumnElement.cast() 操作符在 JSONJSONB 上不再隐式调用 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)
)

#2729

检查约束现在反映

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"))

#3588

Index 添加 tablespace 选项

Index 对象现在接受参数 postgresql_tablespace,以指定 TABLESPACE,与 Table 对象所接受的方式相同。

另请参见

Index Storage Parameters

#3720

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_lockedGenerativeSelect.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)

INSERTON 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)

#3529

ARRAY 和 JSON 类型现在正确指定“不可哈希”

如关于“不可哈希”类型的变更,影响了 ORM 行的去重所述,ORM 在查询的选定实体中混合全 ORM 实体与列表达式时,依赖于能够为列值产生哈希函数。现在,hashable=False 标志已正确设置在所有 PG 的“数据结构”类型上,包括ARRAYJSONJSONBHSTORE 类型已经包括了这个标志。对于ARRAY,这取决于ARRAY.as_tuple 标志,然而,现在应该不再需要设置这个标志,以便在组合的 ORM 行中具有数组值。

另请参见

关于“不可哈希”类型的变更,影响了 ORM 行的去重

从 ARRAY、JSON、HSTORE 的索引访问正确建立 SQL 类型

#3499

从 ARRAY、JSON、HSTORE 的索引访问正确建立 SQL 类型

对于ARRAYJSONHSTORE三者,通过索引访问返回的表达式所分配的 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()
  • JSONJSONB 类型现在与 PostgreSQL 本身对于索引访问的操作一致。这意味着对于 JSONJSONB 类型的所有索引访问都会返回一个表达式,该表达式本身始终JSONJSONB 本身,除非使用了 Comparator.astext 修饰符。这意味着,无论 JSON 结构的索引访问最终指向字符串、列表、数字还是其他 JSON 结构,PostgreSQL 总是将其视为 JSON 本身,除非明确进行了不同的类型转换。与 ARRAY 类型类似,现在可以轻松地生成具有多层索引访问的 JSON 表达式:
json_expr = json_col["key1"]["attr1"][5]
  • 通过对 HSTORE 的索引访问返回的“文本”类型,以及通过对 JSONJSONB 的索引访问返回的“文本”类型,再结合 Comparator.astext 修饰符,现在是可配置的;在这两种情况下,默认为 TextClause,但可以使用 JSON.astext_typeHSTORE.text_type 参数将其设置为用户定义的类型。

另请参阅

JSON cast() 操作现在需要显式调用 .astext

#3499 #3487

JSON cast() 操作现在需要显式调用 .astext

作为 从数组、JSON、HSTORE 的索引访问正确建立 SQL 类型的更改 的一部分,ColumnElement.cast() 操作在 JSONJSONB 上不再隐式调用 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)
)

#2729

检查约束现在反映

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"))

#3588

向 Index 添加 tablespace 选项

Index 对象现在接受参数 postgresql_tablespace,以指定 TABLESPACE,与 Table 对象接受的方式相同。

参见

索引存储参数

#3720

对 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_lockedGenerativeSelect.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_levelConnection.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”属性。

#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",
)

方言改进和变化 - 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 的最新版本中用于提取外键约束的方式相同。

#3629

检查约束现在反映

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 或更高版本生效时,此更改中存在的变通方法现在已经被取消了。

#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 版本中为外键约束所实现的方式一样。

#3629

检查约束现在反映

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_levelConnection.execution_options.isolation_level参数设置事务隔离级别。四个标准级别以及SNAPSHOT都受支持:

engine = create_engine(
    "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ"
)

另请参见

事务隔离级别

#3534 ### 反射时字符串/可变长度类型不再明确表示“max”

当反射诸如StringTextClause等包含长度的类型时,在 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”参数预期只能是整数值或NoneNone表示无限长度,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表示相同的含义。

#3504

支持在主键上使用“非聚集”以允许在其他地方进行聚集

UniqueConstraintPrimaryKeyConstraintIndex 上可用的 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_levelConnection.execution_options.isolation_level参数设置事务隔离级别。四个标准级别都受支持,以及SNAPSHOT

engine = create_engine(
    "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ"
)

另请参阅

事务隔离级别

#3534

字符串/可变长度类型不再在反射时显式表示“max”

当反射像StringTextClause等包含长度的类型时,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视为相同的含义。

#3504

支持在其他地方集群化以允许主键上的“非聚集”

现在UniqueConstraintPrimaryKeyConstraintIndex上可用的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

方言改进和变更 - 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 结构提供结果时,对列名的依赖要少得多,因此这个问题的重要性在任何情况下已经降低了。

#3633

改进对远程模式的支持

SQLite 方言现在实现了Inspector.get_schema_names(),并且对于从远程模式创建和反映的表和索引提供了改进的支持,在 SQLite 中,远程模式是通过ATTACH语句分配名称的数据库;以前,CREATE INDEX DDL 对于绑定模式表的情况无法正确工作,而Inspector.get_foreign_keys()方法现在将在结果中指示给定的模式。不支持跨模式外键。

反映主键约束的名称

SQLite 后端现在利用 SQLite 的“sqlite_master”视图,以从原始 DDL 中提取表的主键约束的名称,就像最近 SQLAlchemy 版本中为外键约束所实现的方式一样。

#3629

检查约束现在反映

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_levelConnection.execution_options.isolation_level参数设置事务隔离级别。四个标准级别以及SNAPSHOT都受支持:

engine = create_engine(
    "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ"
)

另请参见

事务隔离级别

#3534 ### 反射时字符串/可变长度类型不再明确表示“max”

当反射诸如StringTextClause等包含长度的类型时,在 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”参数预期只能是整数值或NoneNone表示无限长度,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表示相同的含义。

#3504

支持在主键上使用“非聚集”以允许在其他地方进行聚集

UniqueConstraintPrimaryKeyConstraintIndex 上可用的 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_levelConnection.execution_options.isolation_level参数设置事务隔离级别。四个标准级别都受支持,以及SNAPSHOT

engine = create_engine(
    "mssql+pyodbc://scott:tiger@ms_2008", isolation_level="REPEATABLE READ"
)

另请参阅

事务隔离级别

#3534

字符串/可变长度类型不再在反射时显式表示“max”

当反射像StringTextClause等包含长度的类型时,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视为相同的含义。

#3504

支持在其他地方集群化以允许主键上的“非聚集”

现在UniqueConstraintPrimaryKeyConstraintIndex上可用的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

方言改进和变更 - 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”后缀。

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