MySQL 和 MariaDB

对 MySQL / MariaDB 数据库的支持。

下表汇总了当前对数据库发布版本的支持级别。

支持的 MySQL / MariaDB 版本

支持类型

版本

支持版本

5.6+ / 10+

尽力而为

5.0.2+ / 5.0.2+

DBAPI 支持

以下方言/DBAPI 选项可用。请参阅各个 DBAPI 部分以获取连接信息。

支持的版本和功能

SQLAlchemy 从 5.0.2 版本开始支持 MySQL,一直到现代版本,以及所有现代版本的 MariaDB。有关特定服务器版本支持的功能的详细信息,请参阅官方 MySQL 文档。

版本 1.4 中的变更: 现在支持的最小 MySQL 版本是 5.0.2。

MariaDB 支持

MariaDB 版本的 MySQL 保持了与 MySQL 协议的基本兼容性,但是这两个产品的开发仍在继续分化。在 SQLAlchemy 领域,这两个数据库在语法和行为方面存在少量差异,SQLAlchemy 会自动进行处理。要连接到 MariaDB 数据库,无需对数据库 URL 进行任何更改。

engine = create_engine("mysql+pymysql://user:pass@some_mariadb/dbname?charset=utf8mb4")

在首次连接时,SQLAlchemy 方言使用服务器版本检测方案来确定后端数据库是否报告为 MariaDB。根据此标志,方言可以在其行为必须不同的区域做出不同的选择。

MariaDB 仅模式

方言还支持可选的“MariaDB 仅”连接模式,这在应用程序使用 MariaDB 特定功能且与 MySQL 数据库不兼容的情况下可能有用。要使用此操作模式,请将上述 URL 中的“mysql”标记替换为“mariadb”。

engine = create_engine("mariadb+pymysql://user:pass@some_mariadb/dbname?charset=utf8mb4")

上述引擎在首次连接时,如果服务器版本检测发现后端数据库不是 MariaDB,则会引发错误。

当使用带有 "mariadb" 作为方言名称的引擎时,所有包含“mysql”名称的 mysql 特定选项现在都以“mariadb”命名。这意味着像 mysql_engine 这样的选项应该命名为 mariadb_engine 等。对于使用带有“mysql”和“mariadb”方言的 URL 的应用程序,可以同时使用“mysql”和“mariadb”选项。

my_table = Table(
    "mytable",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("textdata", String(50)),
    mariadb_engine="InnoDB",
    mysql_engine="InnoDB",
)

Index(
    "textdata_ix",
    my_table.c.textdata,
    mysql_prefix="FULLTEXT",
    mariadb_prefix="FULLTEXT",
)

当上述结构被反射时,也会发生类似的行为,即当数据库 URL 基于“mariadb”名称时,选项名称中将存在“mariadb”前缀。

版本 1.4 中的新增功能: 添加了“mariadb”方言名称,支持对 MySQL 方言的“MariaDB 仅模式”。

连接超时和断开连接

MySQL / MariaDB 具有自动连接关闭行为,对于已空闲一段时间(默认值为 8 小时)的连接,该行为会自动关闭。要避免出现此问题,请使用 create_engine.pool_recycle 选项,它可以确保如果连接在池中存在固定秒数,则该连接将被丢弃并替换为新的连接。

engine = create_engine('mysql+mysqldb://...', pool_recycle=3600)

为了更全面地检测池化连接的断开连接,包括适应服务器重启和网络问题,可以使用预 ping 方法。有关当前方法,请参阅 处理断开连接

另请参阅

处理断开连接 - 有关处理超时连接以及数据库重启的几种技术的背景信息。

包括存储引擎的 CREATE TABLE 参数

MySQL 和 MariaDB 的 CREATE TABLE 语法都包括大量特殊选项,包括 ENGINECHARSETMAX_ROWSROW_FORMATINSERT_METHOD 以及更多。要适应这些参数的渲染,请指定形式 mysql_argument_name="value"。例如,要指定具有 ENGINEInnoDBCHARSETutf8mb4KEY_BLOCK_SIZE1024 的表:

Table('mytable', metadata,
      Column('data', String(32)),
      mysql_engine='InnoDB',
      mysql_charset='utf8mb4',
      mysql_key_block_size="1024"
     )

当支持 MariaDB 仅模式 模式时,还需要包括针对“mariadb”前缀的类似键。当然,这些值可以独立变化,以便可以维护 MySQL 与 MariaDB 上的不同设置。

# support both "mysql" and "mariadb-only" engine URLs

Table('mytable', metadata,
      Column('data', String(32)),

      mysql_engine='InnoDB',
      mariadb_engine='InnoDB',

      mysql_charset='utf8mb4',
      mariadb_charset='utf8',

      mysql_key_block_size="1024"
      mariadb_key_block_size="1024"

     )

MySQL / MariaDB 方言通常会将指定为 mysql_keyword_name 的任何关键字渲染为 KEYWORD_NAME,在 CREATE TABLE 语句中。这些名称中只有少数几个会用空格而不是下划线进行渲染;为了支持这一点,MySQL 方言了解这些特定名称,包括 DATA DIRECTORY(例如 mysql_data_directory)、CHARACTER SET(例如 mysql_character_set)和 INDEX DIRECTORY(例如 mysql_index_directory)。

最常见的参数是 mysql_engine,它指的是表的存储引擎。从历史上看,MySQL 服务器安装默认情况下会将此值设置为 MyISAM,尽管较新版本可能默认设置为 InnoDBInnoDB 引擎通常因为它支持事务和外键而被优先选择。

在 MySQL / MariaDB 数据库中创建的存储引擎为 MyISAMTable 本质上是非事务性的,这意味着任何引用此表的 INSERT/UPDATE/DELETE 语句都将作为自动提交执行。它也不支持外键约束;虽然 CREATE TABLE 语句接受外键选项,但使用 MyISAM 存储引擎时,这些参数会被丢弃。反映这样的表也不会产生任何外键约束信息。

为了完全原子事务以及对外键约束的支持,所有参与的 CREATE TABLE 语句必须指定一个事务引擎,在绝大多数情况下是 InnoDB

大小写敏感和表反射

MySQL 和 MariaDB 对大小写敏感的标识符名称的支持不一致,这取决于底层操作系统的特定细节。但是,据观察,无论存在什么大小写敏感行为,外键声明中表的名称始终从数据库接收为全小写,这使得不可能准确地反映一个架构,其中相关联的表使用混合大小写标识符名称。

因此强烈建议在 SQLAlchemy 以及 MySQL / MariaDB 数据库本身中都将表名声明为全小写,尤其是在要使用数据库反射功能的情况下。

事务隔离级别

所有 MySQL / MariaDB 方言都支持通过方言特定的参数 create_engine.isolation_level(由 create_engine() 接受)以及 Connection.execution_options.isolation_level 参数(传递给 Connection.execution_options())来设置事务隔离级别。此功能通过对每个新连接发出命令 SET SESSION TRANSACTION ISOLATION LEVEL <level> 来实现。对于特殊的 AUTOCOMMIT 隔离级别,使用特定于 DBAPI 的技术。

使用 create_engine() 设置隔离级别

engine = create_engine(
                "mysql+mysqldb://scott:tiger@localhost/test",
                isolation_level="READ UNCOMMITTED"
            )

使用每个连接执行选项设置

connection = engine.connect()
connection = connection.execution_options(
    isolation_level="READ COMMITTED"
)

isolation_level 的有效值包括

  • READ COMMITTED

  • READ UNCOMMITTED

  • REPEATABLE READ

  • SERIALIZABLE

  • AUTOCOMMIT

特殊的 AUTOCOMMIT 值利用了特定 DBAPI 提供的各种“autocommit”属性,目前由 MySQLdb、MySQL-Client、MySQL-Connector Python 和 PyMySQL 支持。使用它,数据库连接将对 SELECT @@autocommit; 的值返回 true。

还有更多用于隔离级别配置的选项,例如与主 Engine 链接的“子引擎”对象,每个对象都应用不同的隔离级别设置。有关背景信息,请参阅 设置事务隔离级别,包括 DBAPI 自动提交 中的讨论。

AUTO_INCREMENT 行为

创建表时,SQLAlchemy 会自动在第一个 Integer 主键列上设置 AUTO_INCREMENT,该列未被标记为外键

>>> t = Table('mytable', metadata,
...   Column('mytable_id', Integer, primary_key=True)
... )
>>> t.create()
CREATE TABLE mytable (
        id INTEGER NOT NULL AUTO_INCREMENT,
        PRIMARY KEY (id)
)

您可以通过将 False 传递给 Column.autoincrement 参数来禁用此行为 Column。此标志也可以用来在某些存储引擎的多列键的辅助列上启用自动递增

Table('mytable', metadata,
      Column('gid', Integer, primary_key=True, autoincrement=False),
      Column('id', Integer, primary_key=True)
     )

服务器端游标

服务器端游标支持适用于 mysqlclient、PyMySQL、mariadbconnector 方言,也可能适用于其他方言。它使用“buffered=True/False”标志(如果可用)或内部使用 MySQLdb.cursors.SSCursorpymysql.cursors.SSCursor 等类来实现。

服务器端游标通过使用 Connection.execution_options.stream_results 连接执行选项在每个语句的基础上启用

with engine.connect() as conn:
    result = conn.execution_options(stream_results=True).execute(text("select * from table"))

请注意,某些类型的 SQL 语句可能不支持服务器端游标;通常,只有返回行的 SQL 语句才能使用此选项。

从版本 1.4 开始弃用: 方言级别的 server_side_cursors 标志已弃用,将在未来版本中删除。请使用 Connection.stream_results 执行选项来获取无缓冲的游标支持。

Unicode

字符集选择

大多数 MySQL / MariaDB DBAPI 提供了设置连接的客户端字符集的选项。这通常通过 URL 中的 charset 参数来实现,例如

e = create_engine(
    "mysql+pymysql://scott:tiger@localhost/test?charset=utf8mb4")

此字符集是连接的 **客户端字符集**。一些 MySQL DBAPI 会将其默认设置为 latin1 等值,而另一些则会使用 my.cnf 文件中的 default-character-set 设置。应参考所用 DBAPI 的文档以了解其具体行为。

用于 Unicode 的编码传统上是 'utf8'。但是,对于 MySQL 版本 5.5.3 及更高版本以及 MariaDB 5.5 及更高版本,引入了新的特定于 MySQL 的编码 'utf8mb4',从 MySQL 8.0 开始,如果在任何服务器端指令中指定了普通的 utf8,服务器就会发出警告,将其替换为 utf8mb3。这种新编码的理由是,MySQL 的传统 utf-8 编码只支持最多三个字节的码位,而不是四个字节。因此,在与包含大于三个字节大小的码位的 MySQL 或 MariaDB 数据库通信时,如果数据库和客户端 DBAPI 都支持这种新的字符集,则优先使用这种字符集,例如

e = create_engine(
    "mysql+pymysql://scott:tiger@localhost/test?charset=utf8mb4")

所有现代 DBAPI 都应该支持 utf8mb4 字符集。

为了对使用传统 utf8 创建的架构使用 utf8mb4 编码,可能需要对 MySQL/MariaDB 架构和/或服务器配置进行更改。

另请参阅

utf8mb4 字符集 - 在 MySQL 文档中

处理二进制数据警告和 Unicode

MySQL 版本 5.6、5.7 及更高版本(在撰写本文时,MariaDB 尚未支持)在尝试将二进制数据传递给数据库时,如果同时使用字符集编码并且二进制数据本身对该编码无效,现在会发出警告

default.py:509: Warning: (1300, "Invalid utf8mb4 character string:
'F9876A'")
  cursor.execute(statement, parameters)

此警告是由于 MySQL 客户端库尝试将二进制字符串解释为 Unicode 对象,即使使用了 LargeBinary 等数据类型。要解决此问题,SQL 语句需要在任何看起来像这样的非 NULL 值之前加上一个二进制“字符集引入器”

INSERT INTO table (data) VALUES (_binary %s)

这些字符集引入器由 DBAPI 驱动程序提供,假设使用 mysqlclient 或 PyMySQL(两者都建议使用)。将查询字符串参数 binary_prefix=true 添加到 URL 以修复此警告

# mysqlclient
engine = create_engine(
    "mysql+mysqldb://scott:tiger@localhost/test?charset=utf8mb4&binary_prefix=true")

# PyMySQL
engine = create_engine(
    "mysql+pymysql://scott:tiger@localhost/test?charset=utf8mb4&binary_prefix=true")

binary_prefix 标志可能被其他 MySQL 驱动程序支持,也可能不支持。

SQLAlchemy 本身无法可靠地渲染这个 _binary 前缀,因为它不适用于 NULL 值,而 NULL 值可以作为绑定参数发送。由于 MySQL 驱动程序将参数直接渲染到 SQL 字符串中,因此这是传递此额外关键字的最有效位置。

另请参阅

字符集引入器 - 在 MySQL 网站上

ANSI 引用样式

MySQL / MariaDB 提供了两种标识符“引用风格”,一种使用反引号,另一种使用引号,例如 `some_identifier` vs. "some_identifier"。所有 MySQL 方言通过检查 sql_mode 的值来检测使用的是哪种版本,该值是在与特定 Engine 首次建立连接时确定的。这种引用风格在渲染表名和列名以及反映现有数据库结构时起作用。检测是完全自动的,使用任何引用风格都不需要特殊配置。

更改 sql_mode

MySQL 支持在服务器和客户端的多个 服务器 SQL 模式 下运行。要更改给定应用程序的 sql_mode,开发者可以使用 SQLAlchemy 的事件系统。

在以下示例中,事件系统用于在 first_connectconnect 事件上设置 sql_mode

from sqlalchemy import create_engine, event

eng = create_engine("mysql+mysqldb://scott:tiger@localhost/test", echo='debug')

# `insert=True` will ensure this is the very first listener to run
@event.listens_for(eng, "connect", insert=True)
def connect(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("SET sql_mode = 'STRICT_ALL_TABLES'")

conn = eng.connect()

在上面所示的示例中,“connect”事件将在为给定池首次创建特定 DBAPI 连接时在连接上调用“SET”语句,然后连接将提供给连接池。此外,由于该函数已使用 insert=True 注册,它将在注册函数的内部列表之前添加。

MySQL / MariaDB SQL 扩展

许多 MySQL / MariaDB SQL 扩展通过 SQLAlchemy 的通用函数和运算符支持来处理

table.select(table.c.password==func.md5('plaintext'))
table.select(table.c.username.op('regexp')('^[a-d]'))

当然,任何有效的 SQL 语句也可以作为字符串执行。

目前,对 MySQL / MariaDB 扩展到 SQL 的有限直接支持可用。

INSERT/DELETE…RETURNING

MariaDB 方言支持 10.5+ 的 INSERT..RETURNINGDELETE..RETURNING (10.0+) 语法。在某些情况下,INSERT..RETURNING 可以自动使用,以检索新生成的标识符,而不是使用传统的 cursor.lastrowid 方法,但是对于简单的单语句情况,cursor.lastrowid 由于其性能更好而目前仍然更受欢迎。

要指定显式 RETURNING 子句,请在每个语句的基础上使用 _UpdateBase.returning() 方法

# INSERT..RETURNING
result = connection.execute(
    table.insert().
    values(name='foo').
    returning(table.c.col1, table.c.col2)
)
print(result.all())

# DELETE..RETURNING
result = connection.execute(
    table.delete().
    where(table.c.name=='foo').
    returning(table.c.col1, table.c.col2)
)
print(result.all())

新版 2.0 中新增:添加了对 MariaDB RETURNING 的支持

INSERT…ON DUPLICATE KEY UPDATE (Upsert)

MySQL / MariaDB 允许通过 ON DUPLICATE KEY UPDATE 子句对 INSERT 语句进行“upsert”(更新或插入)行到表中。只有在该行与表中不存在的现有主键或唯一键匹配时,才会插入候选行;否则,将执行 UPDATE。该语句允许分别指定 INSERT 的值和 UPDATE 的值。

SQLAlchemy 通过 MySQL 特定的 insert() 函数提供 ON DUPLICATE KEY UPDATE 支持,该函数提供生成方法 Insert.on_duplicate_key_update()

>>> 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=insert_stmt.inserted.data,
...     status='U'
... )
>>> print(on_duplicate_key_stmt)
INSERT INTO my_table (id, data) VALUES (%s, %s) ON DUPLICATE KEY UPDATE data = VALUES(data), status = %s

与 PostgreSQL 的“ON CONFLICT”短语不同,“ON DUPLICATE KEY UPDATE”短语将始终匹配任何主键或唯一键,并且如果存在匹配项,将始终执行 UPDATE;它没有选项来引发错误或跳过执行 UPDATE。

ON DUPLICATE KEY UPDATE 用于使用任何组合的新值以及提议插入的值来更新已存在的行。这些值通常使用传递给 Insert.on_duplicate_key_update() 的关键字参数指定,其中给定列键值(通常是列的名称,除非它指定 Column.key)作为键,而字面量或 SQL 表达式作为值

>>> 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(),
... )

>>> print(on_duplicate_key_stmt)
INSERT INTO my_table (id, data) VALUES (%s, %s) ON DUPLICATE KEY UPDATE data = %s, updated_at = CURRENT_TIMESTAMP

UpdateBase.values() 相似,接受其他参数形式,包括单个字典

>>> on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
...     {"data": "some data", "updated_at": func.current_timestamp()},
... )

以及 2 元组列表,它将自动以与 参数有序更新 中所述类似的方式提供参数有序的 UPDATE 语句。与 Update 对象不同,不需要任何特殊标志来指定意图,因为在这种情况下参数形式是明确的

>>> on_duplicate_key_stmt = insert_stmt.on_duplicate_key_update(
...     [
...         ("data", "some data"),
...         ("updated_at", func.current_timestamp()),
...     ]
... )

>>> print(on_duplicate_key_stmt)
INSERT INTO my_table (id, data) VALUES (%s, %s) ON DUPLICATE KEY UPDATE data = %s, updated_at = CURRENT_TIMESTAMP

版本 1.3 中的更改:支持 MySQL ON DUPLICATE KEY UPDATE 中的参数有序 UPDATE 子句

警告

Insert.on_duplicate_key_update() 方法考虑 Python 侧的默认 UPDATE 值或生成函数,例如使用 Column.onupdate 指定的函数。这些值不会在 ON DUPLICATE KEY 样式的 UPDATE 中执行,除非它们在参数中明确指定。

为了引用提议的插入行,可以使用 Insert.inserted 作为 Insert 对象的属性;此对象是 ColumnCollection,它包含目标表的所有列

>>> stmt = insert(my_table).values(
...     id='some_id',
...     data='inserted value',
...     author='jlh')

>>> do_update_stmt = stmt.on_duplicate_key_update(
...     data="updated value",
...     author=stmt.inserted.author
... )

>>> print(do_update_stmt)
INSERT INTO my_table (id, data, author) VALUES (%s, %s, %s) ON DUPLICATE KEY UPDATE data = %s, author = VALUES(author)

渲染时,“inserted”命名空间将生成表达式 VALUES(<columnname>)

版本 1.2 中新增:添加了对 MySQL ON DUPLICATE KEY UPDATE 子句的支持

rowcount 支持

SQLAlchemy 将 DBAPI cursor.rowcount 属性标准化为“受 UPDATE 或 DELETE 语句影响的行数”的通常定义。这与大多数 MySQL DBAPI 驱动程序的默认设置相矛盾,默认设置是“实际修改/删除的行数”。出于这个原因,SQLAlchemy MySQL 方言始终在连接时添加 constants.CLIENT.FOUND_ROWS 标志,或目标方言的等效标志。此设置当前是硬编码的。

另请参阅

CursorResult.rowcount

MySQL / MariaDB 特定索引选项

MySQL 和 MariaDB 对 Index 结构的特定扩展可用。

索引长度

MySQL 和 MariaDB 都提供了一个选项,可以创建具有特定长度的索引条目,其中“长度”指的是每个值中将成为索引一部分的字符或字节数。SQLAlchemy 通过 mysql_length 和/或 mariadb_length 参数提供此功能。

Index('my_index', my_table.c.data, mysql_length=10, mariadb_length=10)

Index('a_b_idx', my_table.c.a, my_table.c.b, mysql_length={'a': 4,
                                                           'b': 9})

Index('a_b_idx', my_table.c.a, my_table.c.b, mariadb_length={'a': 4,
                                                           'b': 9})

对于非二进制字符串类型,前缀长度以字符为单位给出,对于二进制字符串类型,前缀长度以字节为单位给出。传递给关键字参数的值必须是整数(因此,为索引的所有列指定相同的前缀长度值)或字典,其中键是列名,值是对应列的前缀长度值。MySQL 和 MariaDB 仅允许为索引的列指定长度,前提是该列是 CHAR、VARCHAR、TEXT、BINARY、VARBINARY 和 BLOB。

索引前缀

MySQL 存储引擎允许您在创建索引时指定索引前缀。SQLAlchemy 通过 Index 上的 mysql_prefix 参数提供此功能。

Index('my_index', my_table.c.data, mysql_prefix='FULLTEXT')

传递给关键字参数的值将简单地传递给底层的 CREATE INDEX,因此它必须是您的 MySQL 存储引擎的有效索引前缀。

另请参阅

CREATE INDEX - MySQL 文档

索引类型

一些 MySQL 存储引擎允许您在创建索引或主键约束时指定索引类型。SQLAlchemy 通过 Index 上的 mysql_using 参数提供此功能。

Index('my_index', my_table.c.data, mysql_using='hash', mariadb_using='hash')

以及 PrimaryKeyConstraint 上的 mysql_using 参数。

PrimaryKeyConstraint("data", mysql_using='hash', mariadb_using='hash')

传递给关键字参数的值将简单地传递给底层的 CREATE INDEX 或 PRIMARY KEY 子句,因此它必须是您的 MySQL 存储引擎的有效索引类型。

更多信息可以在以下位置找到:

https://dev.mysqlserver.cn/doc/refman/5.0/en/create-index.html

https://dev.mysqlserver.cn/doc/refman/5.0/en/create-table.html

索引解析器

MySQL 中的 CREATE FULLTEXT INDEX 也支持“WITH PARSER”选项。这可以使用关键字参数 mysql_with_parser 来实现。

Index(
    'my_index', my_table.c.data,
    mysql_prefix='FULLTEXT', mysql_with_parser="ngram",
    mariadb_prefix='FULLTEXT', mariadb_with_parser="ngram",
)

新版本 1.3。

MySQL / MariaDB 外键

MySQL 和 MariaDB 关于外键的行为有一些重要的注意事项。

要避免的外键参数

MySQL 和 MariaDB 都不支持外键参数“DEFERRABLE”、“INITIALLY”或“MATCH”。使用 deferrableinitially 关键字参数与 ForeignKeyConstraintForeignKey 将使这些关键字在 DDL 表达式中被渲染,这将在 MySQL 或 MariaDB 上引发错误。为了在 MySQL / MariaDB 后端上忽略这些关键字,同时在使用这些关键字,请使用自定义编译规则。

from sqlalchemy.ext.compiler import compiles
from sqlalchemy.schema import ForeignKeyConstraint

@compiles(ForeignKeyConstraint, "mysql", "mariadb")
def process(element, compiler, **kw):
    element.deferrable = element.initially = None
    return compiler.visit_foreign_key_constraint(element, **kw)

“MATCH”关键字实际上更为阴险,在 SQLAlchemy 与 MySQL 或 MariaDB 后端结合使用时被明确禁止。此参数被 MySQL / MariaDB 静默忽略,但此外,还会导致 ON UPDATE 和 ON DELETE 选项也被后端忽略。因此,MATCH 永远不应该与 MySQL / MariaDB 后端一起使用;与 DEFERRABLE 和 INITIALLY 一样,可以使用自定义编译规则来在 DDL 定义时纠正 ForeignKeyConstraint。

外键约束的反射

并非所有 MySQL / MariaDB 存储引擎都支持外键。当使用非常常见的 MyISAM MySQL 存储引擎时,表反射加载的信息将不包括外键。对于这些表,您可以在反射时提供 ForeignKeyConstraint

Table('mytable', metadata,
      ForeignKeyConstraint(['other_id'], ['othertable.other_id']),
      autoload_with=engine
     )

MySQL / MariaDB 唯一约束和反射

SQLAlchemy 支持带有 unique=True 标志的 Index 结构,表示唯一索引,以及 UniqueConstraint 结构,表示唯一约束。当发出 DDL 以创建这些约束时,MySQL / MariaDB 都支持这两个对象/语法。但是,MySQL / MariaDB 没有独立于唯一索引的唯一约束结构;也就是说,MySQL / MariaDB 上的“UNIQUE”约束等同于创建“UNIQUE INDEX”。

当反射这些结构时,Inspector.get_indexes()Inspector.get_unique_constraints() 方法将同时返回 MySQL / MariaDB 中唯一索引的条目。但是,当使用 Table(..., autoload_with=engine) 执行完整表反射时,UniqueConstraint 结构不是在任何情况下都完全反映的 Table 结构的一部分;此结构始终由具有 unique=True 设置的 Index 表示,该设置存在于 Table.indexes 集合中。

TIMESTAMP / DATETIME 问题

为 MySQL / MariaDB 的 explicit_defaults_for_timestamp 渲染 ON UPDATE CURRENT TIMESTAMP

MySQL / MariaDB 历史上将 TIMESTAMP 数据类型的 DDL 扩展为短语“TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP”,其中包括非标准 SQL,该 SQL 会在发生 UPDATE 时自动使用当前时间戳更新列,从而消除了在需要服务器端更新更改的情况下通常使用触发器的需要。

MySQL 5.6 引入了新标志 explicit_defaults_for_timestamp,它禁用上述行为,在 MySQL 8 中,此标志默认设置为 true,这意味着为了在不更改此标志的情况下获得 MySQL “on update timestamp”,必须显式渲染上述 DDL。此外,相同的 DDL 也适用于使用 DATETIME 数据类型。

SQLAlchemy 的 MySQL 方言尚未提供生成 MySQL 的“ON UPDATE CURRENT_TIMESTAMP”子句的选项,需要注意的是,这不是通用“ON UPDATE”,因为标准 SQL 中没有这种语法。SQLAlchemy 的 Column.server_onupdate 参数当前与这种特殊的 MySQL 行为无关。

要生成此 DDL,请使用 Column.server_default 参数,并传递一个也包含 ON UPDATE 子句的文本子句。

from sqlalchemy import Table, MetaData, Column, Integer, String, TIMESTAMP
from sqlalchemy import text

metadata = MetaData()

mytable = Table(
    "mytable",
    metadata,
    Column('id', Integer, primary_key=True),
    Column('data', String(50)),
    Column(
        'last_updated',
        TIMESTAMP,
        server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    )
)

相同的说明适用于使用 DateTimeDATETIME 数据类型。

from sqlalchemy import DateTime

mytable = Table(
    "mytable",
    metadata,
    Column('id', Integer, primary_key=True),
    Column('data', String(50)),
    Column(
        'last_updated',
        DateTime,
        server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
    )
)

即使 Column.server_onupdate 功能不会生成此 DDL,但仍然可能需要向 ORM 示意应该获取此更新值。这种语法如下所示:

from sqlalchemy.schema import FetchedValue

class MyClass(Base):
    __tablename__ = 'mytable'

    id = Column(Integer, primary_key=True)
    data = Column(String(50))
    last_updated = Column(
        TIMESTAMP,
        server_default=text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP"),
        server_onupdate=FetchedValue()
    )

TIMESTAMP 列和 NULL

MySQL 历史上强制执行,指定 TIMESTAMP 数据类型的列隐式包含 CURRENT_TIMESTAMP 的默认值,即使没有说明,并且还将该列设置为 NOT NULL,这与所有其他数据类型的行为相反。

mysql> CREATE TABLE ts_test (
    -> a INTEGER,
    -> b INTEGER NOT NULL,
    -> c TIMESTAMP,
    -> d TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    -> e TIMESTAMP NULL);
Query OK, 0 rows affected (0.03 sec)

mysql> SHOW CREATE TABLE ts_test;
+---------+-----------------------------------------------------
| Table   | Create Table
+---------+-----------------------------------------------------
| ts_test | CREATE TABLE `ts_test` (
  `a` int(11) DEFAULT NULL,
  `b` int(11) NOT NULL,
  `c` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `d` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `e` timestamp NULL DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1

上面,我们看到 INTEGER 列默认为 NULL,除非它用 NOT NULL 指定。但是,当列的类型为 TIMESTAMP 时,会生成 CURRENT_TIMESTAMP 的隐式默认值,这也会强制该列为 NOT NULL,即使我们没有像这样指定它。

可以使用在 MySQL 5.6 中引入的 explicit_defaults_for_timestamp 配置标志更改 MySQL 方面的此行为。使用此服务器设置启用后,TIMESTAMP 列在关于默认值和可空性方面表现得像 MySQL 方面的任何其他数据类型。

但是,为了适应大多数没有指定这个新标志的 MySQL 数据库,SQLAlchemy 会在任何没有指定 nullable=False 的 TIMESTAMP 列中显式地发出 "NULL" 指定符。为了适应指定了 explicit_defaults_for_timestamp 的较新数据库,SQLAlchemy 还会在指定了 nullable=False 的 TIMESTAMP 列中发出 NOT NULL。以下示例说明了这一点

from sqlalchemy import MetaData, Integer, Table, Column, text
from sqlalchemy.dialects.mysql import TIMESTAMP

m = MetaData()
t = Table('ts_test', m,
        Column('a', Integer),
        Column('b', Integer, nullable=False),
        Column('c', TIMESTAMP),
        Column('d', TIMESTAMP, nullable=False)
    )


from sqlalchemy import create_engine
e = create_engine("mysql+mysqldb://scott:tiger@localhost/test", echo=True)
m.create_all(e)

输出

CREATE TABLE ts_test (
    a INTEGER,
    b INTEGER NOT NULL,
    c TIMESTAMP NULL,
    d TIMESTAMP NOT NULL
)

MySQL SQL 结构

对象名称 描述

match

生成一个 MATCH (X, Y) AGAINST ('TEXT') 子句。

class sqlalchemy.dialects.mysql.match

生成一个 MATCH (X, Y) AGAINST ('TEXT') 子句。

例如

from sqlalchemy import desc
from sqlalchemy.dialects.mysql import match

match_expr = match(
    users_table.c.firstname,
    users_table.c.lastname,
    against="Firstname Lastname",
)

stmt = (
    select(users_table)
    .where(match_expr.in_boolean_mode())
    .order_by(desc(match_expr))
)

将生成类似的 SQL

SELECT id, firstname, lastname
FROM user
WHERE MATCH(firstname, lastname) AGAINST (:param_1 IN BOOLEAN MODE)
ORDER BY MATCH(firstname, lastname) AGAINST (:param_2) DESC

The match() 函数是所有 SQL 表达式上可用的 ColumnElement.match() 方法的独立版本,就像使用 ColumnElement.match() 一样,但是它允许传递多个列

参数:
  • cols – 要匹配的列表达式

  • against – 要比较的表达式

  • in_boolean_mode – 布尔值,将 “boolean mode” 设置为 true

  • in_natural_language_mode – 布尔值,将 “natural language” 设置为 true

  • with_query_expansion – 布尔值,将 “query expansion” 设置为 true

版本 1.4.19 中的新增内容。

另请参阅

ColumnElement.match()

类签名

class sqlalchemy.dialects.mysql.match (sqlalchemy.sql.expression.Generative, sqlalchemy.sql.expression.BinaryExpression)

method sqlalchemy.dialects.mysql.match.in_boolean_mode() Self

在 MATCH 表达式上应用 "IN BOOLEAN MODE" 修饰符。

返回值:

一个新的 match 实例,其中应用了修改。

method sqlalchemy.dialects.mysql.match.in_natural_language_mode() Self

在 MATCH 表达式上应用 "IN NATURAL LANGUAGE MODE" 修饰符。

返回值:

一个新的 match 实例,其中应用了修改。

attribute sqlalchemy.dialects.mysql.match.inherit_cache: bool | None = True

指示此 HasCacheKey 实例是否应该使用其直接超类使用的缓存键生成方案。

该属性默认为 None,这表示一个构造尚未考虑其是否适合参与缓存;这在功能上等同于将值设置为 False,只是还会发出警告。

如果与对象对应的 SQL 不基于此类的局部属性(而不是其超类)而更改,则可以将此标志设置为 True

另请参阅

为自定义构造启用缓存支持 - 为第三方或用户定义的 SQL 构造设置 HasCacheKey.inherit_cache 属性的一般指南。

method sqlalchemy.dialects.mysql.match.with_query_expansion() Self

在 MATCH 表达式上应用 "WITH QUERY EXPANSION" 修饰符。

返回值:

一个新的 match 实例,其中应用了修改。

MySQL 数据类型

与所有 SQLAlchemy 方言一样,所有已知对 MySQL 有效的 UPPERCASE 类型都可以从顶级方言中导入

from sqlalchemy.dialects.mysql import (
    BIGINT,
    BINARY,
    BIT,
    BLOB,
    BOOLEAN,
    CHAR,
    DATE,
    DATETIME,
    DECIMAL,
    DECIMAL,
    DOUBLE,
    ENUM,
    FLOAT,
    INTEGER,
    LONGBLOB,
    LONGTEXT,
    MEDIUMBLOB,
    MEDIUMINT,
    MEDIUMTEXT,
    NCHAR,
    NUMERIC,
    NVARCHAR,
    REAL,
    SET,
    SMALLINT,
    TEXT,
    TIME,
    TIMESTAMP,
    TINYBLOB,
    TINYINT,
    TINYTEXT,
    VARBINARY,
    VARCHAR,
    YEAR,
)

特定于 MySQL 或具有 MySQL 特定构造参数的类型如下

对象名称 描述

BIGINT

MySQL BIGINTEGER 类型。

BIT

MySQL BIT 类型。

CHAR

MySQL CHAR 类型,用于固定长度的字符数据。

DATETIME

MySQL DATETIME 类型。

DECIMAL

MySQL DECIMAL 类型。

ENUM

MySQL ENUM 类型。

FLOAT

MySQL FLOAT 类型。

INTEGER

MySQL INTEGER 类型。

JSON

MySQL JSON 类型。

LONGBLOB

MySQL LONGBLOB 类型,用于最多 2^32 字节的二进制数据。

LONGTEXT

MySQL LONGTEXT 类型,用于最多 2^32 字节的字符存储。

MEDIUMBLOB

MySQL MEDIUMBLOB 类型,用于最多 2^24 字节的二进制数据。

MEDIUMINT

MySQL MEDIUMINTEGER 类型。

MEDIUMTEXT

MySQL MEDIUMTEXT 类型,用于最多 2^24 字节的字符存储。

NCHAR

MySQL NCHAR 类型。

NUMERIC

MySQL NUMERIC 类型。

NVARCHAR

MySQL NVARCHAR 类型。

REAL

MySQL REAL 类型。

SET

MySQL SET 类型。

SMALLINT

MySQL SMALLINTEGER 类型。

TIME

MySQL TIME 类型。

TIMESTAMP

MySQL TIMESTAMP 类型。

TINYBLOB

MySQL TINYBLOB 类型,用于最多 2^8 字节的二进制数据。

TINYINT

MySQL TINYINT 类型。

TINYTEXT

MySQL TINYTEXT 类型,用于最多 2^8 字节的字符存储。

VARCHAR

MySQL VARCHAR 类型,用于可变长度的字符数据。

YEAR

MySQL YEAR 类型,用于存储 1901-2155 年的单字节。

class sqlalchemy.dialects.mysql.BIGINT

MySQL BIGINTEGER 类型。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.BIGINT (sqlalchemy.dialects.mysql.types._IntegerType, sqlalchemy.types.BIGINT)

method sqlalchemy.dialects.mysql.BIGINT.__init__(display_width=None, **kw)

构造一个 BIGINTEGER。

参数:
  • display_width – 可选,此数字的最大显示宽度。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为 true,则值将存储为左侧用零填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

class sqlalchemy.dialects.mysql.BINARY

SQL BINARY 类型。

类签名

class sqlalchemy.dialects.mysql.BINARY (sqlalchemy.types._Binary)

class sqlalchemy.dialects.mysql.BIT

MySQL BIT 类型。

此类型适用于 MyISAM 的 MySQL 5.0.3 或更高版本,以及 MyISAM、MEMORY、InnoDB 和 BDB 的 5.0.5 或更高版本。对于旧版本,请使用 MSTinyInteger() 类型。

成员

__init__()

method sqlalchemy.dialects.mysql.BIT.__init__(length=None)

构造一个 BIT。

参数:

length – 可选,位数。

class sqlalchemy.dialects.mysql.BLOB

SQL BLOB 类型。

类签名

class sqlalchemy.dialects.mysql.BLOB (sqlalchemy.types.LargeBinary)

method sqlalchemy.dialects.mysql.BLOB.__init__(length: int | None = None)

继承自 sqlalchemy.types.LargeBinary.__init__ 方法 LargeBinary

构造一个 LargeBinary 类型。

参数:

length – 可选,用于 DDL 语句的列长度,对于接受长度的那些二进制类型,例如 MySQL BLOB 类型。

class sqlalchemy.dialects.mysql.BOOLEAN

SQL BOOLEAN 类型。

类签名

class sqlalchemy.dialects.mysql.BOOLEAN (sqlalchemy.types.Boolean)

method sqlalchemy.dialects.mysql.BOOLEAN.__init__(create_constraint: bool = False, name: str | None = None, _create_events: bool = True, _adapted_from: SchemaType | None = None)

继承自 sqlalchemy.types.Boolean.__init__ 方法 Boolean

构造一个 Boolean。

参数:
  • create_constraint

    默认为 False。如果布尔值被生成为 int/smallint,还会在表上创建一个 CHECK 约束,以确保值为 1 或 0。

    注意

    强烈建议 CHECK 约束有一个明确的名称,以便支持架构管理问题。这可以通过设置 Boolean.name 参数或设置适当的命名约定来实现;有关背景信息,请参阅 配置约束命名约定

    版本 1.4 中的变更: - 此标志现在默认为 False,这意味着不会为非本机枚举类型生成 CHECK 约束。

  • name – 如果生成 CHECK 约束,请指定约束的名称。

class sqlalchemy.dialects.mysql.CHAR

MySQL CHAR 类型,用于固定长度的字符数据。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.CHAR (sqlalchemy.dialects.mysql.types._StringType, sqlalchemy.types.CHAR)

method sqlalchemy.dialects.mysql.CHAR.__init__(length=None, **kwargs)

构造一个 CHAR。

参数:
  • length – 最大数据长度(以字符为单位)。

  • binary – 可选,使用国家字符集的默认二进制排序规则。这不会影响存储的数据类型,请使用 BINARY 类型存储二进制数据。

  • collation – 可选,请求特定排序规则。必须与国家字符集兼容。

class sqlalchemy.dialects.mysql.DATE

SQL DATE 类型。

类签名

class sqlalchemy.dialects.mysql.DATE (sqlalchemy.types.Date)

class sqlalchemy.dialects.mysql.DATETIME

MySQL DATETIME 类型。

成员

__init__()

method sqlalchemy.dialects.mysql.DATETIME.__init__(timezone=False, fsp=None)

构造一个 MySQL DATETIME 类型。

参数:
  • timezone – MySQL 方言未使用。

  • fsp

    小数秒精度值。MySQL 5.6.4 支持小数秒的存储;此参数将在为 DATETIME 类型发出 DDL 时使用。

    注意

    DBAPI 驱动程序对小数秒的支持可能有限;当前支持包括 MySQL Connector/Python。

class sqlalchemy.dialects.mysql.DECIMAL

MySQL DECIMAL 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.DECIMAL (sqlalchemy.dialects.mysql.types._NumericType, sqlalchemy.types.DECIMAL)

方法 sqlalchemy.dialects.mysql.DECIMAL.__init__(precision=None, scale=None, asdecimal=True, **kw)

构造一个 DECIMAL。

参数:
  • precision – 此数字的总位数。如果 scale 和 precision 都为 None,则将值存储到服务器允许的限制范围内。

  • scale – 小数点后的位数。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为真,则值将存储为用零左填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

sqlalchemy.dialects.mysql.DOUBLE

MySQL DOUBLE 类型。

类签名

sqlalchemy.dialects.mysql.DOUBLE (sqlalchemy.dialects.mysql.types._FloatType, sqlalchemy.types.DOUBLE)

方法 sqlalchemy.dialects.mysql.DOUBLE.__init__(precision=None, scale=None, asdecimal=True, **kw)

构造一个 DOUBLE。

注意

默认情况下,DOUBLE 类型将从浮点数转换为 Decimal,使用默认情况下为 10 位的截断。指定 scale=ndecimal_return_scale=n 来更改此比例,或指定 asdecimal=False 来直接将值作为 Python 浮点数返回。

参数:
  • precision – 此数字的总位数。如果 scale 和 precision 都为 None,则将值存储到服务器允许的限制范围内。

  • scale – 小数点后的位数。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为真,则值将存储为用零左填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

sqlalchemy.dialects.mysql.ENUM

MySQL ENUM 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.ENUM (sqlalchemy.types.NativeForEmulated, sqlalchemy.types.Enum, sqlalchemy.dialects.mysql.types._StringType)

方法 sqlalchemy.dialects.mysql.ENUM.__init__(*enums, **kw)

构造一个 ENUM。

例如

Column('myenum', ENUM("foo", "bar", "baz"))
参数:
  • enums

    此 ENUM 的有效值范围。ENUM 中的值不会被引号括起来,它们将在生成模式时被转义并用单引号括起来。此对象也可以是符合 PEP-435 的枚举类型。

  • strict

    此标志没有影响。

    在版本 The 中更改: MySQL ENUM 类型以及基本 Enum 类型现在验证所有 Python 数据值。

  • charset – 可选,此字符串值的列级字符集。优先于“ascii”或“unicode”简写。

  • collation – 可选,此字符串值的列级排序规则。优先于“binary”简写。

  • ascii – 默认值为 False:latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:ucs2 字符集的简写,在模式中生成 UNICODE。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储数据的类型,只会影响字符数据的排序规则。

sqlalchemy.dialects.mysql.FLOAT

MySQL FLOAT 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.FLOAT (sqlalchemy.dialects.mysql.types._FloatType, sqlalchemy.types.FLOAT)

方法 sqlalchemy.dialects.mysql.FLOAT.__init__(precision=None, scale=None, asdecimal=False, **kw)

构造一个 FLOAT。

参数:
  • precision – 此数字的总位数。如果 scale 和 precision 都为 None,则将值存储到服务器允许的限制范围内。

  • scale – 小数点后的位数。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为真,则值将存储为用零左填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

sqlalchemy.dialects.mysql.INTEGER

MySQL INTEGER 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.INTEGER (sqlalchemy.dialects.mysql.types._IntegerType, sqlalchemy.types.INTEGER)

方法 sqlalchemy.dialects.mysql.INTEGER.__init__(display_width=None, **kw)

构造一个 INTEGER。

参数:
  • display_width – 可选,此数字的最大显示宽度。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为 True,值将存储为左对齐并用零填充的字符串。请注意,这不会影响底层数据库 API 返回的值,它们仍然是数字。

class sqlalchemy.dialects.mysql.JSON

MySQL JSON 类型。

MySQL 从 5.7 版本开始支持 JSON。MariaDB 从 10.2 版本开始支持 JSON(作为 LONGTEXT 的别名)。

JSON 在使用基本 JSON 数据类型针对 MySQL 或 MariaDB 后端时自动使用。

另请参阅

JSON - 通用跨平台 JSON 数据类型的基本文档。

JSON 类型支持 JSON 值的持久化以及 JSON 数据类型提供的核心索引操作,方法是通过调整操作来在数据库级别呈现 JSON_EXTRACT 函数。

class sqlalchemy.dialects.mysql.LONGBLOB

MySQL LONGBLOB 类型,用于最多 2^32 字节的二进制数据。

类签名

class sqlalchemy.dialects.mysql.LONGBLOB (sqlalchemy.types._Binary)

class sqlalchemy.dialects.mysql.LONGTEXT

MySQL LONGTEXT 类型,用于最多 2^32 字节的字符存储。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.LONGTEXT (sqlalchemy.dialects.mysql.types._StringType)

method sqlalchemy.dialects.mysql.LONGTEXT.__init__(**kwargs)

构造一个 LONGTEXT。

参数:
  • charset – 可选,此字符串值的列级字符集。优先于“ascii”或“unicode”简写。

  • collation – 可选,此字符串值的列级排序规则。优先于“binary”简写。

  • ascii – 默认值为 False:latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:ucs2 字符集的简写,在模式中生成 UNICODE。

  • national – 可选。如果为 True,使用服务器配置的国家字符集。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储的数据类型,只会影响字符数据的排序规则。

class sqlalchemy.dialects.mysql.MEDIUMBLOB

MySQL MEDIUMBLOB 类型,用于最多 2^24 字节的二进制数据。

类签名

class sqlalchemy.dialects.mysql.MEDIUMBLOB (sqlalchemy.types._Binary)

class sqlalchemy.dialects.mysql.MEDIUMINT

MySQL MEDIUMINTEGER 类型。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.MEDIUMINT (sqlalchemy.dialects.mysql.types._IntegerType)

method sqlalchemy.dialects.mysql.MEDIUMINT.__init__(display_width=None, **kw)

构造一个 MEDIUMINTEGER

参数:
  • display_width – 可选,此数字的最大显示宽度。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为 True,值将存储为左对齐并用零填充的字符串。请注意,这不会影响底层数据库 API 返回的值,它们仍然是数字。

class sqlalchemy.dialects.mysql.MEDIUMTEXT

MySQL MEDIUMTEXT 类型,用于最多 2^24 字节的字符存储。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.MEDIUMTEXT (sqlalchemy.dialects.mysql.types._StringType)

method sqlalchemy.dialects.mysql.MEDIUMTEXT.__init__(**kwargs)

构造一个 MEDIUMTEXT。

参数:
  • charset – 可选,此字符串值的列级字符集。优先于“ascii”或“unicode”简写。

  • collation – 可选,此字符串值的列级排序规则。优先于“binary”简写。

  • ascii – 默认值为 False:latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:ucs2 字符集的简写,在模式中生成 UNICODE。

  • national – 可选。如果为 True,使用服务器配置的国家字符集。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储的数据类型,只会影响字符数据的排序规则。

class sqlalchemy.dialects.mysql.NCHAR

MySQL NCHAR 类型。

用于服务器配置的国家字符集中的固定长度字符数据。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.NCHAR (sqlalchemy.dialects.mysql.types._StringType, sqlalchemy.types.NCHAR)

method sqlalchemy.dialects.mysql.NCHAR.__init__(length=None, **kwargs)

构造一个 NCHAR。

参数:
  • length – 最大数据长度,以字符为单位。

  • binary – 可选,使用国家字符集的默认二进制排序规则。这不会影响存储的数据类型,请使用 BINARY 类型存储二进制数据。

  • collation – 可选,请求特定排序规则。必须与国家字符集兼容。

class sqlalchemy.dialects.mysql.NUMERIC

MySQL NUMERIC 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.NUMERIC (sqlalchemy.dialects.mysql.types._NumericType, sqlalchemy.types.NUMERIC)

方法 sqlalchemy.dialects.mysql.NUMERIC.__init__(precision=None, scale=None, asdecimal=True, **kw)

构造一个 NUMERIC。

参数:
  • precision – 此数字的总位数。如果 scale 和 precision 都为 None,则值将存储到服务器允许的限制。

  • scale – 小数点后的位数。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为 True,则值将存储为用零左填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

sqlalchemy.dialects.mysql.NVARCHAR

MySQL NVARCHAR 类型。

用于服务器配置的国家字符集中的可变长度字符数据。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.NVARCHAR (sqlalchemy.dialects.mysql.types._StringType, sqlalchemy.types.NVARCHAR)

方法 sqlalchemy.dialects.mysql.NVARCHAR.__init__(length=None, **kwargs)

构造一个 NVARCHAR。

参数:
  • length – 最大数据长度(以字符为单位)。

  • binary – 可选,使用国家字符集的默认二进制排序规则。这不会影响存储的数据类型,请使用 BINARY 类型存储二进制数据。

  • collation – 可选,请求特定的排序规则。必须与国家字符集兼容。

sqlalchemy.dialects.mysql.REAL

MySQL REAL 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.REAL (sqlalchemy.dialects.mysql.types._FloatType, sqlalchemy.types.REAL)

方法 sqlalchemy.dialects.mysql.REAL.__init__(precision=None, scale=None, asdecimal=True, **kw)

构造一个 REAL。

注意

默认情况下,REAL 类型将从 float 转换为 Decimal,使用截断,默认为 10 位数。指定 scale=ndecimal_return_scale=n 来更改此比例,或者 asdecimal=False 将值直接返回为 Python 浮点数。

参数:
  • precision – 此数字的总位数。如果 scale 和 precision 都为 None,则值将存储到服务器允许的限制。

  • scale – 小数点后的位数。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为 True,则值将存储为用零左填充的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数字。

sqlalchemy.dialects.mysql.SET

MySQL SET 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.SET (sqlalchemy.dialects.mysql.types._StringType)

方法 sqlalchemy.dialects.mysql.SET.__init__(*values, **kw)

构造一个 SET。

例如

Column('myset', SET("foo", "bar", "baz"))

如果此集合将用于生成表的 DDL,或者如果 SET.retrieve_as_bitwise 标志设置为 True,则需要提供潜在值的列表。

参数:
  • values – 此 SET 的有效值范围。这些值不带引号,它们将在生成模式时被转义并用单引号括起来。

  • convert_unicode – 与 String.convert_unicode 中的标志相同。

  • collation – 与 String.collation 中的标志相同。

  • charset – 与 VARCHAR.charset 中的标志相同。

  • ascii – 与 VARCHAR.ascii 中的标志相同。

  • unicode – 与 VARCHAR.unicode 中的标志相同。

  • binary – 与 VARCHAR.binary 中的标志相同。

  • retrieve_as_bitwise

    如果为 True,则集合类型的将使用整数来持久化和选择,其中集合会强制转换为位掩码以进行持久化。MySQL 允许这种模式,这种模式的优点是可以明确地存储值,例如空字符串 ''。数据类型将在 SELECT 语句中显示为表达式 col + 0,以便该值在结果集中强制转换为整数。如果要持久化一个可以存储空字符串 '' 作为值的集合,则需要此标志。

    警告

    使用 SET.retrieve_as_bitwise 时,必须确保集合值的列表以与 MySQL 数据库中存在的 **完全相同的顺序** 表达。

sqlalchemy.dialects.mysql.SMALLINT

MySQL SMALLINTEGER 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.SMALLINT (sqlalchemy.dialects.mysql.types._IntegerType, sqlalchemy.types.SMALLINT)

方法 sqlalchemy.dialects.mysql.SMALLINT.__init__(display_width=None, **kw)

构造 SMALLINTEGER。

参数:
  • display_width – 可选,此数字的最大显示宽度。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为真,则值将存储为左填充零的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数值。

sqlalchemy.dialects.mysql.TEXT

MySQL TEXT 类型,用于存储编码高达 2^16 字节的字符。

类签名

sqlalchemy.dialects.mysql.TEXT (sqlalchemy.dialects.mysql.types._StringType, sqlalchemy.types.TEXT)

方法 sqlalchemy.dialects.mysql.TEXT.__init__(length=None, **kw)

构造 TEXT。

参数:
  • length – 可选,如果提供,服务器可能会通过替换最小的 TEXT 类型来优化存储,该类型足以存储 length 字节的字符。

  • charset – 可选,此字符串值的列级字符集。优先于“ascii”或“unicode”简写。

  • collation – 可选,此字符串值的列级排序规则。优先于“binary”简写。

  • ascii – 默认值为 False:用于 latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:用于 ucs2 字符集的简写,在模式中生成 UNICODE。

  • national – 可选。如果为真,请使用服务器配置的国家/地区字符集。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储的数据类型,只会影响字符数据的排序规则。

sqlalchemy.dialects.mysql.TIME

MySQL TIME 类型。

成员

__init__()

方法 sqlalchemy.dialects.mysql.TIME.__init__(timezone=False, fsp=None)

构造 MySQL TIME 类型。

参数:
  • timezone – MySQL 方言未使用。

  • fsp

    小数秒精度值。MySQL 5.6 支持存储小数秒;此参数将在为 TIME 类型发出 DDL 时使用。

    注意

    DBAPI 驱动程序对小数秒的支持可能有限;当前支持包括 MySQL Connector/Python。

sqlalchemy.dialects.mysql.TIMESTAMP

MySQL TIMESTAMP 类型。

成员

__init__()

方法 sqlalchemy.dialects.mysql.TIMESTAMP.__init__(timezone=False, fsp=None)

构造 MySQL TIMESTAMP 类型。

参数:
  • timezone – MySQL 方言未使用。

  • fsp

    小数秒精度值。MySQL 5.6.4 支持存储小数秒;此参数将在为 TIMESTAMP 类型发出 DDL 时使用。

    注意

    DBAPI 驱动程序对小数秒的支持可能有限;当前支持包括 MySQL Connector/Python。

sqlalchemy.dialects.mysql.TINYBLOB

MySQL TINYBLOB 类型,用于最多 2^8 字节的二进制数据。

类签名

sqlalchemy.dialects.mysql.TINYBLOB (sqlalchemy.types._Binary)

sqlalchemy.dialects.mysql.TINYINT

MySQL TINYINT 类型。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.TINYINT (sqlalchemy.dialects.mysql.types._IntegerType)

方法 sqlalchemy.dialects.mysql.TINYINT.__init__(display_width=None, **kw)

构造 TINYINT。

参数:
  • display_width – 可选,此数字的最大显示宽度。

  • unsigned – 布尔值,可选。

  • zerofill – 可选。如果为真,则值将存储为左填充零的字符串。请注意,这不会影响底层数据库 API 返回的值,这些值仍然是数值。

sqlalchemy.dialects.mysql.TINYTEXT

MySQL TINYTEXT 类型,用于最多 2^8 字节的字符存储。

成员

__init__()

类签名

sqlalchemy.dialects.mysql.TINYTEXT (sqlalchemy.dialects.mysql.types._StringType)

方法 sqlalchemy.dialects.mysql.TINYTEXT.__init__(**kwargs)

构造 TINYTEXT。

参数:
  • charset – 可选,此字符串值的列级字符集。优先于“ascii”或“unicode”简写。

  • collation – 可选,此字符串值的列级排序规则。优先于“binary”简写。

  • ascii – 默认值为 False:用于 latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:ucs2 字符集的简写,在模式中生成 UNICODE。

  • national – 可选。如果为 True,则使用服务器配置的国家字符集。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储的数据类型,而只会影响字符数据的排序规则。

class sqlalchemy.dialects.mysql.VARBINARY

SQL VARBINARY 类型。

类签名

class sqlalchemy.dialects.mysql.VARBINARY (sqlalchemy.types._Binary)

class sqlalchemy.dialects.mysql.VARCHAR

MySQL VARCHAR 类型,用于可变长度的字符数据。

成员

__init__()

类签名

class sqlalchemy.dialects.mysql.VARCHAR (sqlalchemy.dialects.mysql.types._StringType, sqlalchemy.types.VARCHAR)

method sqlalchemy.dialects.mysql.VARCHAR.__init__(length=None, **kwargs)

构造一个 VARCHAR。

参数:
  • charset – 可选,此字符串值的列级字符集。优先于 'ascii' 或 'unicode' 简写。

  • collation – 可选,此字符串值的列级排序规则。优先于 'binary' 简写。

  • ascii – 默认值为 False:latin1 字符集的简写,在模式中生成 ASCII。

  • unicode – 默认值为 False:ucs2 字符集的简写,在模式中生成 UNICODE。

  • national – 可选。如果为 True,则使用服务器配置的国家字符集。

  • binary – 默认值为 False:简写,选择与列字符集匹配的二进制排序规则类型。在模式中生成 BINARY。这不会影响存储的数据类型,而只会影响字符数据的排序规则。

class sqlalchemy.dialects.mysql.YEAR

MySQL YEAR 类型,用于存储 1901-2155 年的单字节。

MySQL DML 结构

对象名称 描述

insert(table)

构造一个 MySQL/MariaDB 特定变体 Insert 结构。

Insert

MySQL 特定的 INSERT 实现。

function sqlalchemy.dialects.mysql.insert(table: _DMLTableArgument) Insert

构造一个 MySQL/MariaDB 特定变体 Insert 结构。

The sqlalchemy.dialects.mysql.insert() function creates a sqlalchemy.dialects.mysql.Insert. This class is based on the dialect-agnostic Insert construct which may be constructed using the insert() function in SQLAlchemy Core.

The Insert construct includes additional methods Insert.on_duplicate_key_update().

class sqlalchemy.dialects.mysql.Insert

MySQL 特定的 INSERT 实现。

添加了用于 MySQL 特定语法的 方法,例如 ON DUPLICATE KEY UPDATE。

The Insert object is created using the sqlalchemy.dialects.mysql.insert() function.

新版本 1.2 中添加。

attribute sqlalchemy.dialects.mysql.Insert.inherit_cache: bool | None = False

指示此 HasCacheKey 实例是否应该使用其直接超类使用的缓存键生成方案。

该属性默认为 None,这表示一个构造尚未考虑其是否适合参与缓存;这在功能上等同于将值设置为 False,只是还会发出警告。

如果与对象对应的 SQL 不基于此类的局部属性(而不是其超类)而更改,则可以将此标志设置为 True

另请参阅

为自定义构造启用缓存支持 - 为第三方或用户定义的 SQL 构造设置 HasCacheKey.inherit_cache 属性的一般指南。

attribute sqlalchemy.dialects.mysql.Insert.inserted

为 ON DUPLICATE KEY UPDATE 语句提供 “inserted” 命名空间

MySQL 的 ON DUPLICATE KEY UPDATE 子句允许通过名为 VALUES() 的特殊函数引用要插入的行。此属性提供该行中的所有列,以便在 ON DUPLICATE KEY UPDATE 子句中以 VALUES() 函数形式引用它们。此属性名为 .inserted,以避免与现有 Insert.values() 方法冲突。

提示

The Insert.inserted attribute is an instance of ColumnCollection, which provides an interface the same as that of the Table.c collection described at Accessing Tables and Columns. With this collection, ordinary names are accessible like attributes (e.g. stmt.inserted.some_column), but special names and dictionary method names should be accessed using indexed access, such as stmt.inserted["column name"] or stmt.inserted["values"]. See the docstring for ColumnCollection for further examples.

另请参阅

INSERT…ON DUPLICATE KEY UPDATE (Upsert) - example of how to use Insert.inserted

method sqlalchemy.dialects.mysql.Insert.on_duplicate_key_update(*args: Mapping[Any, Any] | List[Tuple[str, Any]] | ColumnCollection[Any, Any], **kw: Any) Self

指定 ON DUPLICATE KEY UPDATE 子句。

参数:

**kw** – 与 UPDATE 值链接的列键。这些值可以是任何 SQL 表达式或支持的字面 Python 值。

警告

此字典**不**考虑 Python 指定的默认 UPDATE 值或生成函数,例如使用 Column.onupdate 指定的函数。这些值不会在 ON DUPLICATE KEY UPDATE 类型的 UPDATE 中执行,除非在此处手动指定值。

参数:

*args

作为传递键/值参数的替代方案,可以将字典或 2 元组列表作为单个位置参数传递。

传递单个字典等同于关键字参数形式

insert().on_duplicate_key_update({"name": "some name"})

传递 2 元组列表表示 UPDATE 子句中的参数分配应按发送顺序排序,类似于 Update 构造在 Parameter Ordered Updates 中的整体描述。

insert().on_duplicate_key_update(
    [("name", "some name"), ("value", "some value")])

Changed in version 1.3: 参数可以指定为字典或 2 元组列表;后者提供了参数排序。

新版本 1.2 中添加。

mysqlclient (MySQL-Python 的分支)

通过 mysqlclient (MySQL-Python 的维护分支) 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 mysqlclient (MySQL-Python 的维护分支) 的文档和下载信息(如果适用)可在以下位置获得:https://pypi.ac.cn/project/mysqlclient/

连接

连接字符串

mysql+mysqldb://<user>:<password>@<host>[:<port>]/<dbname>

驱动程序状态

mysqlclient DBAPI 是 MySQL-Python DBAPI 的维护分支,该分支不再维护。 mysqlclient 支持 Python 2 和 Python 3,并且非常稳定。

Unicode

有关 Unicode 处理的当前建议,请参见 Unicode

SSL 连接

mysqlclient 和 PyMySQL DBAPI 接受键“ssl”下的附加字典,可以使用 create_engine.connect_args 字典指定。

engine = create_engine(
    "mysql+mysqldb://scott:[email protected]/test",
    connect_args={
        "ssl": {
            "ca": "/home/gord/client-ssl/ca.pem",
            "cert": "/home/gord/client-ssl/client-cert.pem",
            "key": "/home/gord/client-ssl/client-key.pem"
        }
    }
)

为了方便起见,以下键也可以在 URL 内联指定,它们将在 URL 中自动解释为“ssl”字典: “ssl_ca”, “ssl_cert”, “ssl_key”, “ssl_capath”, “ssl_cipher”, “ssl_check_hostname”。以下是一个示例

connection_uri = (
    "mysql+mysqldb://scott:[email protected]/test"
    "?ssl_ca=/home/gord/client-ssl/ca.pem"
    "&ssl_cert=/home/gord/client-ssl/client-cert.pem"
    "&ssl_key=/home/gord/client-ssl/client-key.pem"
)

另请参阅

SSL 连接 在 PyMySQL 方言中

在 Google Cloud SQL 中使用 MySQLdb

Google Cloud SQL 现在建议使用 MySQLdb 方言。使用类似于以下 URL 的 URL 连接

mysql+mysqldb://root@/<dbname>?unix_socket=/cloudsql/<projectid>:<instancename>

服务器端游标

mysqldb 方言支持服务器端游标。请参见 服务器端游标

PyMySQL

通过 PyMySQL 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 PyMySQL 的文档和下载信息(如果适用)可在以下位置获得:https://py.mysqlserver.cn/

连接

连接字符串

mysql+pymysql://<username>:<password>@<host>/<dbname>[?<options>]

Unicode

有关 Unicode 处理的当前建议,请参见 Unicode

SSL 连接

PyMySQL DBAPI 接受与 MySQLdb 相同的 SSL 参数,如 SSL 连接 中所述。请参见该部分以获取其他示例。

如果服务器使用自签名的自动生成证书或证书与主机名不匹配(从客户端的角度来看),则可能还需要在 PyMySQL 中指定 ssl_check_hostname=false

connection_uri = (
    "mysql+pymysql://scott:[email protected]/test"
    "?ssl_ca=/home/gord/client-ssl/ca.pem"
    "&ssl_cert=/home/gord/client-ssl/client-cert.pem"
    "&ssl_key=/home/gord/client-ssl/client-key.pem"
    "&ssl_check_hostname=false"
)

MySQL-Python 兼容性

pymysql DBAPI 是 MySQL-python (MySQLdb) 驱动程序的纯 Python 端口,旨在实现 100% 兼容。大多数针对 MySQL-python 的行为说明也适用于 pymysql 驱动程序。

MariaDB-Connector

通过 MariaDB Connector/Python 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 MariaDB Connector/Python 的文档和下载信息(如果适用)可在以下位置获得:https://pypi.ac.cn/project/mariadb/

连接

连接字符串

mariadb+mariadbconnector://<user>:<password>@<host>[:<port>]/<dbname>

驱动程序状态

MariaDB Connector/Python 使 Python 程序能够使用符合 Python DB API 2.0 (PEP-249) 的 API 访问 MariaDB 和 MySQL 数据库。它用 C 编写,使用 MariaDB Connector/C 客户端库进行客户端服务器通信。

请注意,mariadb:// 连接 URI 的默认驱动程序仍然是 mysqldb。 要使用此驱动程序,需要 mariadb+mariadbconnector://

MySQL-Connector

通过 MySQL Connector/Python 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 MySQL Connector/Python 的文档和下载信息(如果适用)可在以下位置获得:https://pypi.ac.cn/project/mysql-connector-python/

连接

连接字符串

mysql+mysqlconnector://<user>:<password>@<host>[:<port>]/<dbname>

注意

自 MySQL Connector/Python 发布以来,该 DBAPI 存在很多问题,其中一些问题可能尚未解决,并且 mysqlconnector 方言**未在 SQLAlchemy 的持续集成中进行测试**。建议使用的 MySQL 方言是 mysqlclient 和 PyMySQL。

asyncmy

通过 asyncmy 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 asyncmy 的文档和下载信息(如果适用)可在以下位置获得:https://github.com/long2ice/asyncmy

连接

连接字符串

mysql+asyncmy://user:password@host:port/dbname[?key=value&key=value...]

使用特殊的 asyncio 中介层,asyncmy 方言可用作 SQLAlchemy asyncio 扩展包的后端。

此方言通常仅应与 create_async_engine() 引擎创建函数一起使用

from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("mysql+asyncmy://user:pass@hostname/dbname?charset=utf8mb4")

aiomysql

通过 aiomysql 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 aiomysql 的文档和下载信息(如果适用)可在以下位置获得:https://github.com/aio-libs/aiomysql

连接

连接字符串

mysql+aiomysql://user:password@host:port/dbname[?key=value&key=value...]

aiomysql 方言是 SQLAlchemy 的第二个 Python asyncio 方言。

使用特殊的 asyncio 中介层,aiomysql 方言可用作 SQLAlchemy asyncio 扩展包的后端。

此方言通常仅应与 create_async_engine() 引擎创建函数一起使用

from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine("mysql+aiomysql://user:pass@hostname/dbname?charset=utf8mb4")

cymysql

通过 CyMySQL 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 CyMySQL 的文档和下载信息(如果适用)可在以下位置获得:https://github.com/nakagami/CyMySQL

连接

连接字符串

mysql+cymysql://<username>:<password>@<host>/<dbname>[?<options>]

注意

CyMySQL 方言**未在 SQLAlchemy 的持续集成中进行测试**,可能存在未解决的问题。建议使用的 MySQL 方言是 mysqlclient 和 PyMySQL。

pyodbc

通过 PyODBC 驱动程序支持 MySQL / MariaDB 数据库。

DBAPI

有关 PyODBC 的文档和下载信息(如果适用)可在以下位置获得:https://pypi.ac.cn/project/pyodbc/

连接

连接字符串

mysql+pyodbc://<username>:<password>@<dsnname>

注意

用于 MySQL 的 PyODBC 方言**未在 SQLAlchemy 的持续集成中进行测试**。推荐的 MySQL 方言是 mysqlclient 和 PyMySQL。但是,如果您想使用 mysql+pyodbc 方言并需要对utf8mb4 字符(包括表情符号等补充字符)提供完全支持,请确保使用最新的 MySQL Connector/ODBC 版本,并在您的 DSN 或连接字符串中指定驱动程序的“ANSI”(**不是**“Unicode”)版本。

传递精确的 pyodbc 连接字符串

import urllib
connection_string = (
    'DRIVER=MySQL ODBC 8.0 ANSI Driver;'
    'SERVER=localhost;'
    'PORT=3307;'
    'DATABASE=mydb;'
    'UID=root;'
    'PWD=(whatever);'
    'charset=utf8mb4;'
)
params = urllib.parse.quote_plus(connection_string)
connection_uri = "mysql+pyodbc:///?odbc_connect=%s" % params