文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 98%

15.1.9 ALTER TABLE 语句15.1.9 ALTER TABLE Statement

ALTER TABLE tbl_name
    [alter_option [, alter_option] ...]
    [partition_options]

alter_option: {
    table_options
  | ADD [COLUMN] col_name column_definition
        [FIRST | AFTER col_name]
  | ADD [COLUMN] (col_name column_definition,...)
  | ADD {INDEX | KEY} [index_name]
        [index_type] (key_part,...) [index_option] ...
  | ADD {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name]
        (key_part,...) [index_option] ...
  | ADD [CONSTRAINT [symbol]] PRIMARY KEY
        [index_type] (key_part,...)
        [index_option] ...
  | ADD [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY]
        [index_name] [index_type] (key_part,...)
        [index_option] ...
  | ADD [CONSTRAINT [symbol]] FOREIGN KEY
        [index_name] (col_name,...)
        reference_definition
  | ADD [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
  | DROP {CHECK | CONSTRAINT} symbol
  | ALTER {CHECK | CONSTRAINT} symbol [NOT] ENFORCED
  | ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}
  | ALTER [COLUMN] col_name {
        SET DEFAULT {literal | (expr)}
      | SET {VISIBLE | INVISIBLE}
      | DROP DEFAULT
    }
  | ALTER INDEX index_name {VISIBLE | INVISIBLE}
  | CHANGE [COLUMN] old_col_name new_col_name column_definition
        [FIRST | AFTER col_name]
  | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]
  | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
  | {DISABLE | ENABLE} KEYS
  | {DISCARD | IMPORT} TABLESPACE
  | DROP [COLUMN] col_name
  | DROP {INDEX | KEY} index_name
  | DROP PRIMARY KEY
  | DROP FOREIGN KEY fk_symbol
  | FORCE
  | LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
  | MODIFY [COLUMN] col_name column_definition
        [FIRST | AFTER col_name]
  | ORDER BY col_name [, col_name] ...
  | RENAME COLUMN old_col_name TO new_col_name
  | RENAME {INDEX | KEY} old_index_name TO new_index_name
  | RENAME [TO | AS] new_tbl_name
  | {WITHOUT | WITH} VALIDATION
}

partition_options:
    partition_option [partition_option] ...

partition_option: {
    ADD PARTITION (partition_definition)
  | DROP PARTITION partition_names
  | DISCARD PARTITION {partition_names | ALL} TABLESPACE
  | IMPORT PARTITION {partition_names | ALL} TABLESPACE
  | TRUNCATE PARTITION {partition_names | ALL}
  | COALESCE PARTITION number
  | REORGANIZE PARTITION partition_names INTO (partition_definitions)
  | EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH | WITHOUT} VALIDATION]
  | ANALYZE PARTITION {partition_names | ALL}
  | CHECK PARTITION {partition_names | ALL}
  | OPTIMIZE PARTITION {partition_names | ALL}
  | REBUILD PARTITION {partition_names | ALL}
  | REPAIR PARTITION {partition_names | ALL}
  | REMOVE PARTITIONING
}

key_part: {col_name [(length)] | (expr)} [ASC | DESC]

index_type:
    USING {BTREE | HASH}

index_option: {
    KEY_BLOCK_SIZE [=] value
  | index_type
  | WITH PARSER parser_name
  | COMMENT 'string'
  | {VISIBLE | INVISIBLE}
}

table_options:
    table_option [[,] table_option] ...

table_option: {
    AUTOEXTEND_SIZE [=] value
  | AUTO_INCREMENT [=] value
  | AVG_ROW_LENGTH [=] value
  | [DEFAULT] CHARACTER SET [=] charset_name
  | CHECKSUM [=] {0 | 1}
  | [DEFAULT] COLLATE [=] collation_name
  | COMMENT [=] 'string'
  | COMPRESSION [=] {'ZLIB' | 'LZ4' | 'NONE'}
  | CONNECTION [=] 'connect_string'
  | {DATA | INDEX} DIRECTORY [=] 'absolute path to directory'
  | DELAY_KEY_WRITE [=] {0 | 1}
  | ENCRYPTION [=] {'Y' | 'N'}
  | ENGINE [=] engine_name
  | ENGINE_ATTRIBUTE [=] 'string'
  | INSERT_METHOD [=] { NO | FIRST | LAST }
  | KEY_BLOCK_SIZE [=] value
  | MAX_ROWS [=] value
  | MIN_ROWS [=] value
  | PACK_KEYS [=] {0 | 1 | DEFAULT}
  | PASSWORD [=] 'string'
  | ROW_FORMAT [=] {DEFAULT | DYNAMIC | FIXED | COMPRESSED | REDUNDANT | COMPACT}
  | SECONDARY_ENGINE_ATTRIBUTE [=] 'string'
  | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1}
  | STATS_PERSISTENT [=] {DEFAULT | 0 | 1}
  | STATS_SAMPLE_PAGES [=] value
  | TABLESPACE tablespace_name [STORAGE {DISK | MEMORY}]
  | UNION [=] (tbl_name[,tbl_name]...)
}

partition_options:
    (see CREATE TABLE options)

ALTER TABLE 用于更改表的结构。例如,您可以添加或删除列,创建或删除索引,更改现有列的类型,或重命名列或表本身。您还可以更改诸如表使用的存储引擎或表注释等特性。ALTER TABLE changes the structure of a table. For example, you can add or delete columns, create or destroy indexes, change the type of existing columns, or rename columns or the table itself. You can also change characteristics such as the storage engine used for the table or the table comment.

ALTER TABLE 语句还有几个附加方面,本节在以下主题下进行了描述:There are several additional aspects to the ALTER TABLE statement, described under the following topics in this section:

表选项Table Options

table_options 表示可以在 CREATE TABLE 语句中使用的表选项,例如 ENGINE、AUTO_INCREMENT、AVG_ROW_LENGTH、MAX_ROWS、ROW_FORMAT 或 TABLESPACE。table_options signifies table options of the kind that can be used in the CREATE TABLE statement, such as ENGINE, AUTO_INCREMENT, AVG_ROW_LENGTH, MAX_ROWS, ROW_FORMAT, or TABLESPACE.

有关所有表选项的描述,请参见 第 15.1.20 节,“CREATE TABLE 语句”。然而,当作为表选项提供时,ALTER TABLE 会忽略 DATA DIRECTORY 和 INDEX DIRECTORY。ALTER TABLE 仅允许它们作为分区选项,并且要求您具有 FILE 权限。For descriptions of all table options, see Section 15.1.20, “CREATE TABLE Statement”. However, ALTER TABLE ignores DATA DIRECTORY and INDEX DIRECTORY when given as table options. ALTER TABLE permits them only as partitioning options, and requires that you have the FILE privilege.

在 ALTER TABLE 中使用表选项提供了一种方便的方式来修改单个表的特性。例如:Use of table options with ALTER TABLE provides a convenient way of altering single table characteristics. For example:

  • 如果 t1 当前不是 InnoDB 表,此语句会将其存储引擎更改为 InnoDB:If t1 is currently not an InnoDB table, this statement changes its storage engine to InnoDB:

    ALTER TABLE t1 ENGINE = InnoDB;
    
  • 要将 InnoDB 表更改为使用压缩行存储格式:To change the InnoDB table to use compressed row-storage format:

    ALTER TABLE t1 ROW_FORMAT = COMPRESSED;
    
  • ENCRYPTION 子句用于启用或禁用 InnoDB 表的页级数据加密。必须安装并配置密钥环插件才能启用加密。The ENCRYPTION clause enables or disables page-level data encryption for an InnoDB table. A keyring plugin must be installed and configured to enable encryption.

    如果启用了 table_encryption_privilege_check 变量,则使用与默认模式加密设置不同的 ENCRYPTION 子句时,需要 TABLE_ENCRYPTION_ADMIN 权限。If the table_encryption_privilege_check variable is enabled, the TABLE_ENCRYPTION_ADMIN privilege is required to use an ENCRYPTION clause with a setting that differs from the default schema encryption setting.

    ENCRYPTION 也支持位于通用表空间中的表。ENCRYPTION is also supported for tables residing in general tablespaces.

    对于位于通用表空间中的表,表和表空间的加密必须匹配。For tables that reside in general tablespaces, table and tablespace encryption must match.

    ENCRYPTION 选项仅由 InnoDB 存储引擎支持;因此,它仅在表已经使用 InnoDB(并且您没有更改表的存储引擎)时有效,或如果 ALTER TABLE 语句同时指定 ENGINE=InnoDB。否则,该语句会被拒绝,并返回 ER_CHECK_NOT_IMPLEMENTED。The ENCRYPTION option is supported only by the InnoDB storage engine; thus it works only if the table already uses InnoDB (and you do not change the table's storage engine), or if the ALTER TABLE statement also specifies ENGINE=InnoDB. Otherwise the statement is rejected with ER_CHECK_NOT_IMPLEMENTED.

    在没有明确指定 ENCRYPTION 子句的情况下,不允许通过将表移动到不同的表空间或更改存储引擎来更改表的加密。Altering table encryption by moving a table to a different tablespace or changing the storage engine is not permitted without explicitly specifying an ENCRYPTION clause.

    如果表使用的存储引擎不支持加密,则不允许在ENCRYPTION子句中指定除'N'或''之外的值。尝试在启用了加密的模式中使用不支持加密的存储引擎创建没有ENCRYPTION子句的表也是不允许的。Specifying an ENCRYPTION clause with a value other than 'N' or '' is not permitted if the table uses a storage engine that does not support encryption. Attempting to create a table without an ENCRYPTION clause in an encryption-enabled schema using a storage engine that does not support encryption is also not permitted.

    有关更多信息,请参见第 17.13 节,“InnoDB 静态数据加密”。For more information, see Section 17.13, “InnoDB Data-at-Rest Encryption”.

  • 要重置当前的自增值:To reset the current auto-increment value:

    ALTER TABLE t1 AUTO_INCREMENT = 13;
    

    您不能将计数器重置为小于或等于当前正在使用的值。对于 InnoDB 和 MyISAM,如果该值小于或等于 AUTO_INCREMENT 列当前的最大值,则该值将被重置为当前 AUTO_INCREMENT 列最大值加一。You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.

  • 要更改默认表字符集:To change the default table character set:

    ALTER TABLE t1 CHARACTER SET = utf8mb4;
    

    另请参见 更改字符集。See also Changing the Character Set.

  • 添加(或更改)表注释:To add (or change) a table comment:

    ALTER TABLE t1 COMMENT = 'New table comment';
    
  • 使用ALTER TABLE并配合TABLESPACE选项,可以在现有的通用表空间、每表文件表空间和系统表空间之间移动InnoDB表。请参阅使用 ALTER TABLE 在表空间之间移动表。Use ALTER TABLE with the TABLESPACE option to move InnoDB tables between existing general tablespaces, file-per-table tablespaces, and the system tablespace. See Moving Tables Between Tablespaces Using ALTER TABLE.

    • ALTER TABLE ... TABLESPACE 操作总是会导致表的完全重建,即使 TABLESPACE 属性没有改变。ALTER TABLE ... TABLESPACE operations always cause a full table rebuild, even if the TABLESPACE attribute has not changed from its previous value.

    • ALTER TABLE ... TABLESPACE 语法不支持将表从临时表空间移动到永久表空间。ALTER TABLE ... TABLESPACE syntax does not support moving a table from a temporary tablespace to a persistent tablespace.

    • 与 DATA DIRECTORY 一起支持的 CREATE TABLE ... TABLESPACE 子句,在 ALTER TABLE ... TABLESPACE 中不被支持,如果指定将被忽略。The DATA DIRECTORY clause, which is supported with CREATE TABLE ... TABLESPACE, is not supported with ALTER TABLE ... TABLESPACE, and is ignored if specified.

    • 有关 TABLESPACE 选项的功能和限制的更多信息,请参阅 CREATE TABLE。For more information about the capabilities and limitations of the TABLESPACE option, see CREATE TABLE.

  • MySQL NDB Cluster 8.4 支持为 NDB_TABLE 选项设置表的分区平衡(碎片计数类型)、任意副本读取功能、完全复制或这些功能的任意组合,作为 ALTER TABLE 语句的表注释的一部分,其方式与 CREATE TABLE 相同,如以下示例所示:MySQL NDB Cluster 8.4 supports setting NDB_TABLE options for controlling a table's partition balance (fragment count type), read-from-any-replica capability, full replication, or any combination of these, as part of the table comment for an ALTER TABLE statement in the same manner as for CREATE TABLE, as shown in this example:

    ALTER TABLE t1 COMMENT = "NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RA_BY_NODE";
    

    也可以为 NDB 表的列设置 NDB_COMMENT 选项,作为 ALTER TABLE 语句的一部分,如下所示:It is also possible to set NDB_COMMENT options for columns of NDB tables as part of an ALTER TABLE statement, like this one:

    ALTER TABLE t1 
      CHANGE COLUMN c1 c1 BLOB 
        COMMENT = 'NDB_COLUMN=BLOB_INLINE_SIZE=4096,MAX_BLOB_PART_SIZE';
    

    请记住,ALTER TABLE ... COMMENT ... 会丢弃表的任何现有注释。有关更多信息和示例,请参阅 设置 NDB_TABLE 选项。Bear in mind that ALTER TABLE ... COMMENT ... discards any existing comment for the table. See Setting NDB_TABLE options, for additional information and examples.

  • ENGINE_ATTRIBUTE 和 SECONDARY_ENGINE_ATTRIBUTE 选项用于为主存储引擎和辅助存储引擎指定表、列和索引的属性。这些选项保留以供将来使用。索引属性不能更改。必须先删除索引,然后以所需更改重新添加索引,这可以在单个 ALTER TABLE 语句中完成。ENGINE_ATTRIBUTE and SECONDARY_ENGINE_ATTRIBUTE options are used to specify table, column, and index attributes for primary and secondary storage engines. These options are reserved for future use. Index attributes cannot be altered. An index must be dropped and added back with the desired change, which can be performed in a single ALTER TABLE statement.

要验证表选项是否按预期更改,请使用 SHOW CREATE TABLE,或查询信息模式 TABLES 表。To verify that the table options were changed as intended, use SHOW CREATE TABLE, or query the Information Schema TABLES table.

性能和空间需求Performance and Space Requirements

ALTER TABLE 操作使用以下算法之一处理:ALTER TABLE operations are processed using one of the following algorithms:

  • COPY:操作在原始表的副本上执行,并且表数据从原始表逐行复制到新表。并发 DML 不允许。COPY: Operations are performed on a copy of the original table, and table data is copied from the original table to the new table row by row. Concurrent DML is not permitted.

  • INPLACE:操作避免复制表数据,但可能会在原地重建表。在操作的准备和执行阶段,可能会短暂获取表的独占元数据锁。通常支持并发 DML。INPLACE: Operations avoid copying table data but may rebuild the table in place. An exclusive metadata lock on the table may be taken briefly during preparation and execution phases of the operation. Typically, concurrent DML is supported.

  • INSTANT:操作仅修改数据字典中的元数据。在操作的执行阶段,可能会短暂获取表的独占元数据锁。表数据不受影响,使操作几乎是瞬时的。允许并发 DML。INSTANT: Operations only modify metadata in the data dictionary. An exclusive metadata lock on the table may be taken briefly during the execution phase of the operation. Table data is unaffected, making operations instantaneous. Concurrent DML is permitted.

对于使用 NDB 存储引擎的表,这些算法的工作方式如下:For tables using the NDB storage engine, these algorithms work as follows:

  • COPYNDB 创建表的副本并进行修改;NDB 集群处理程序随后在表的旧版本和新版本之间复制数据。随后,NDB 删除了旧表并重命名了新表。COPY: NDB creates a copy of the table and alters it; the NDB Cluster handler then copies the data between the old and new versions of the table. Subsequently, NDB deletes the old table and renames the new one.

    这有时也被称为 “copying” 或 “offline” ALTER TABLE。This is sometimes also referred to as a “copying” or “offline” ALTER TABLE.

  • INPLACE:数据节点进行必要的更改;NDB 集群处理器不复制数据,也不参与。INPLACE: The data nodes make the required changes; the NDB Cluster handler does not copy data or otherwise take part.

    这有时也被称为 “非复制” 或 “在线” ALTER TABLE。This is sometimes also referred to as a “non-copying” or “online” ALTER TABLE.

  • INSTANT:不被支持NDB.INSTANT: Not supported by NDB.

参见第 25.6.12 节,“NDB 集群中使用 ALTER TABLE 的在线操作”,以获取更多信息。See Section 25.6.12, “Online Operations with ALTER TABLE in NDB Cluster”, for more information.

ALGORITHM 子句为可选。如果省略了 ALGORITHM 子句,MySQL 在存储引擎中使用 ALGORITHM=INSTANTALTER TABLE 支持该子句。否则,使用 ALGORITHM=INPLACE。如果不支持 ALGORITHM=INPLACE,则使用 ALGORITHM=COPY。The ALGORITHM clause is optional. If the ALGORITHM clause is omitted, MySQL uses ALGORITHM=INSTANT for storage engines and ALTER TABLE clauses that support it. Otherwise, ALGORITHM=INPLACE is used. If ALGORITHM=INPLACE is not supported, ALGORITHM=COPY is used.

Note

在使用 ALGORITHM=INSTANT 向分区表添加列之后,无法再对该表执行 ALTER TABLE ... EXCHANGE PARTITION 操作。After adding a column to a partitioned table using ALGORITHM=INSTANT, it is no longer possible to perform ALTER TABLE ... EXCHANGE PARTITION on the table.

指定 ALGORITHM 子句要求操作使用支持该子句和存储引擎的指定算法,否则将报错。指定 ALGORITHM=DEFAULT 与省略 ALGORITHM 子句的效果相同。Specifying an ALGORITHM clause requires the operation to use the specified algorithm for clauses and storage engines that support it, or fail with an error otherwise. Specifying ALGORITHM=DEFAULT is the same as omitting the ALGORITHM clause.

ALTER TABLE 操作使用 COPY 算法,等待其他修改表的操作完成。在对表复制应用修改后,数据被复制,原始表被删除,表复制被重命名为原始表的名称。当 ALTER TABLE执行时,原始表仍可被其他会话读取(后文提到的例外)。在ALTER TABLE 操作开始后,对表的更新和写入会暂停,直到新表准备好,然后自动重定向到新表。表的临时副本会在原始表的数据库目录中创建,除非是 RENAME TO 操作,将表移动到位于不同目录中的数据库。ALTER TABLE operations that use the COPY algorithm wait for other operations that are modifying the table to complete. After alterations are applied to the table copy, data is copied over, the original table is deleted, and the table copy is renamed to the name of the original table. While the ALTER TABLE operation executes, the original table is readable by other sessions (with the exception noted shortly). Updates and writes to the table started after the ALTER TABLE operation begins are stalled until the new table is ready, then are automatically redirected to the new table. The temporary copy of the table is created in the database directory of the original table unless it is a RENAME TO operation that moves the table to a database that resides in a different directory.

之前提到的例外是 ALTER TABLE 在准备清除表和表定义缓存中过时的表结构时,阻断读取(不仅仅是写入)。此时,它必须获得一个独占锁。为此,它等待当前读者完成,并阻止新的读写。The exception referred to earlier is that ALTER TABLE blocks reads (not just writes) at the point where it is ready to clear outdated table structures from the table and table definition caches. At this point, it must acquire an exclusive lock. To do so, it waits for current readers to finish, and blocks new reads and writes.

使用 COPY 算法的 ALTER TABLE 操作会阻止并发的 DML 操作。并发查询仍然允许。也就是说,表复制操作至少包括 LOCK=SHARED 的并发限制(允许查询,但不允许 DML)。对于支持 LOCK 子句的操作,可以进一步通过指定 LOCK=EXCLUSIVE 来限制并发,这将阻止 DML 和查询。有关更多信息,请参见 并发控制。An ALTER TABLE operation that uses the COPY algorithm prevents concurrent DML operations. Concurrent queries are still allowed. That is, a table-copying operation always includes at least the concurrency restrictions of LOCK=SHARED (allow queries but not DML). You can further restrict concurrency for operations that support the LOCK clause by specifying LOCK=EXCLUSIVE, which prevents DML and queries. For more information, see Concurrency Control.

要强制使用 COPY 算法,用于 ALTER TABLE 操作,否则该操作本不使用该操作,请指定 ALGORITHM=COPY或启用 old_alter_table 系统变量。如果old_alter_tableALGORITHM子句之间存在冲突,且其值非DEFAULT值,则ALGORITHM子句优先。To force use of the COPY algorithm for an ALTER TABLE operation that would otherwise not use it, specify ALGORITHM=COPY or enable the old_alter_table system variable. If there is a conflict between the old_alter_table setting and an ALGORITHM clause with a value other than DEFAULT, the ALGORITHM clause takes precedence.

表,如果没有任何可变长度列(InnoDB表,一个ALTER TABLE在表上使用该算法的操作,该表位于COPY共享表空间中可能会增加表空间的使用量。这类操作所需的额外空间与表中的数据加上索引相等。对于位于共享表空间中的表,操作期间使用的额外空间不会像位于每表文件表空间中的表那样释放回操作系统。,不同于For InnoDB tables, an ALTER TABLE operation that uses the COPY algorithm on a table that resides in a shared tablespace can increase the amount of space used by the tablespace. Such operations require as much additional space as the data in the table plus indexes. For a table residing in a shared tablespace, the additional space used during the operation is not released back to the operating system as it is for a table that resides in a file-per-table tablespace.

有关在线 DDL 操作空间需求的信息,请参见第 17.12.3 节,“在线 DDL 空间需求”。For information about space requirements for online DDL operations, see Section 17.12.3, “Online DDL Space Requirements”.

ALTER TABLE 支持 INPLACE 算法的操作包括:ALTER TABLE operations that support the INPLACE algorithm include:

  • ALTER TABLE 操作由 InnoDB 的 在线 DDL 功能支持。请参阅 第 17.12.1 节,“在线 DDL 操作”。ALTER TABLE operations supported by the InnoDB online DDL feature. See Section 17.12.1, “Online DDL Operations”.

  • 重命名表。MySQL 会重命名与表 tbl_name 对应的文件,而不进行复制。(你也可以使用 RENAME TABLE 语句来重命名表。参阅 第 15.1.36 节,“RENAME TABLE 语句”。)专门授予重命名表的权限不会迁移到新名称。它们必须手动更改。Renaming a table. MySQL renames files that correspond to the table tbl_name without making a copy. (You can also use the RENAME TABLE statement to rename tables. See Section 15.1.36, “RENAME TABLE Statement”.) Privileges granted specifically for the renamed table are not migrated to the new name. They must be changed manually.

  • 仅修改表元数据的操作。这些操作是即时的,因为服务器不会接触表内容。仅限元数据的操作包括:Operations that modify table metadata only. These operations are immediate because the server does not touch table contents. Metadata-only operations include:

    • 重命名列。在 NDB 集群中,此操作也可以在线执行。Renaming a column. In NDB Cluster, this operation can also be performed online.

    • 更改列的默认值(NDB 表除外)。Changing the default value of a column (except for NDB tables).

    • 通过在有效成员值列表的末尾添加新的枚举或集合成员来修改ENUM或SET列的定义,只要数据类型的存储大小不变。例如,向具有 8 个成员的SET列添加一个成员会将每个值所需的存储从 1 字节改为 2 字节;这需要复制表。在列表中间添加成员会导致现有成员的重新编号,这也需要复制表。Modifying the definition of an ENUM or SET column by adding new enumeration or set members to the end of the list of valid member values, as long as the storage size of the data type does not change. For example, adding a member to a SET column that has 8 members changes the required storage per value from 1 byte to 2 bytes; this requires a table copy. Adding members in the middle of the list causes renumbering of existing members, which requires a table copy.

    • 更改空间列的定义以移除SRID属性。(添加或更改SRID属性需要重建,无法就地完成,因为服务器必须验证所有值具有指定的SRID值。)Changing the definition of a spatial column to remove the SRID attribute. (Adding or changing an SRID attribute requires a rebuild, and cannot be done in place, because the server must verify that all values have the specified SRID value.)

    • 在满足以下条件时更改列的字符集:Changing a column character set, when these conditions apply:

      • 列的数据类型是 CHAR、VARCHAR、TEXT 类型,或者 ENUM。The column data type is CHAR, VARCHAR, a TEXT type, or ENUM.

      • 字符集的更改是从 utf8mb3 到 utf8mb4,或者从任意字符集到 binary。The character set change is from utf8mb3 to utf8mb4, or any character set to binary.

      • 该列没有索引。There is no index on the column.

    • 在满足以下条件时更改生成列:Changing a generated column, when these conditions apply:

      • 对于 InnoDB 表,修改生成的存储列但不更改其类型、表达式或可空性的语句。For InnoDB tables, statements that modify generated stored columns but do not change their type, expression, or nullability.

      • 对于非 InnoDB 表,修改生成的存储或虚拟列但不更改其类型、表达式或可空性的语句。For non-InnoDB tables, statements that modify generated stored or virtual columns but do not change their type, expression, or nullability.

      这种更改的一个例子是更改列注释。An example of such a change is a change to the column comment.

  • 重命名索引。Renaming an index.

  • 为 InnoDB 和 NDB 表添加或删除二级索引。参见 第 17.12.1 节,“在线 DDL 操作”。Adding or dropping a secondary index, for InnoDB and NDB tables. See Section 17.12.1, “Online DDL Operations”.

  • 对于 NDB 表,可以对可变宽度列进行添加和删除索引的操作。这些操作在线进行,无需复制表,并且在大部分持续时间内不会阻塞并发 DML 操作。参见 第 25.6.12 节,“在 NDB 集群中使用 ALTER TABLE 的在线操作”。For NDB tables, operations that add and drop indexes on variable-width columns. These operations occur online, without table copying and without blocking concurrent DML actions for most of their duration. See Section 25.6.12, “Online Operations with ALTER TABLE in NDB Cluster”.

  • 使用 ALTER INDEX 操作修改索引可见性。Modifying index visibility with an ALTER INDEX operation.

  • 对包含依赖于具有 DEFAULT 值列的生成列的表进行列修改,如果被修改的列不涉及生成列表达式。例如,单独列的 NULL 属性更改可以在原地完成,而无需重建表。Column modifications of tables containing generated columns that depend on columns with a DEFAULT value if the modified columns are not involved in the generated column expressions. For example, changing the NULL property of a separate column can be done in place without a table rebuild.

支持 INSTANT 算法的 ALTER TABLE 操作包括:ALTER TABLE operations that support the INSTANT algorithm include:

  • 添加列。此功能称为“Instant ADD COLUMN”。存在限制。参见 第 17.12.1 节,“在线 DDL 操作”。Adding a column. This feature is referred to as “Instant ADD COLUMN”. Limitations apply. See Section 17.12.1, “Online DDL Operations”.

  • 删除列。此功能称为“Instant DROP COLUMN”。存在限制。参见 第 17.12.1 节,“在线 DDL 操作”。Dropping a column. This feature is referred to as “Instant DROP COLUMN”. Limitations apply. See Section 17.12.1, “Online DDL Operations”.

  • 添加或删除虚拟列。Adding or dropping a virtual column.

  • 添加或删除列默认值。Adding or dropping a column default value.

  • 修改 ENUM 或 SET 列的定义。与上述针对 ALGORITHM=INSTANT 所描述的限制相同。Modifying the definition of an ENUM or SET column. The same restrictions apply as described above for ALGORITHM=INSTANT.

  • 正在更改索引类型。Changing the index type.

  • 重命名表。对 ALGORITHM=INSTANT。Renaming a table. The same restrictions apply as described above for ALGORITHM=INSTANT.

有关支持 ALGORITHM=INSTANT,请参见 第 17.12.1 节,“在线 DDL 操作”。For more information about operations that support ALGORITHM=INSTANT, see Section 17.12.1, “Online DDL Operations”.

ALTER TABLE 将 MySQL 5.5 时序列升级为 5.6 格式,支持 ADD COLUMN,CHANGE COLUMNMODIFY COLUMNADD INDEXFORCE 操作。此转换不能使用 INPLACE,因为表格需要重建,因此在此情况下指定 ALGORITHM=INPLACE 会导致错误。如有必要,指定 ALGORITHM=COPY。ALTER TABLE upgrades MySQL 5.5 temporal columns to 5.6 format for ADD COLUMN, CHANGE COLUMN, MODIFY COLUMN, ADD INDEX, and FORCE operations. This conversion cannot be done using the INPLACE algorithm because the table must be rebuilt, so specifying ALGORITHM=INPLACE in these cases results in an error. Specify ALGORITHM=COPY if necessary.

如果对多列索引进行 ALTER TABLE 操作,用于用 KEY,则只能使用 ALGORITHM=COPY。If an ALTER TABLE operation on a multicolumn index used to partition a table by KEY changes the order of the columns, it can only be performed using ALGORITHM=COPY.

WITHOUT VALIDATION 和 WITH VALIDATION 子句会影响 ALTER TABLE virtual generated column modifications。参见 第 15.1.9.2 节,“ALTER TABLE 和生成列”。The WITHOUT VALIDATION and WITH VALIDATION clauses affect whether ALTER TABLE performs an in-place operation for virtual generated column modifications. See Section 15.1.9.2, “ALTER TABLE and Generated Columns”.

NDB Cluster 8.4 支持使用与标准 MySQL 服务器相同的 ALGORITHM=INPLACE 语法的在线操作。NDB 不允许在线更改表空间。更多信息请参见 第 25.6.12 节,“使用 ALTER TABLE 在 NDB 集群中的在线操作”。NDB Cluster 8.4 supports online operations using the same ALGORITHM=INPLACE syntax used with the standard MySQL Server. NDB does not allow changing a tablespace online. See Section 25.6.12, “Online Operations with ALTER TABLE in NDB Cluster”, for more information.

执行复制 ALTER TABLE,NDB 检查是否对受影响的表进行并发写入。如果发现有此类情况,NDB 拒绝 ALTER TABLE 语句,并提出 ER_TABLE_DEF_CHANGED。When performing a copying ALTER TABLE, NDB checks to ensure that no concurrent writes have been made to the affected table. If it finds that any have been made, NDB rejects the ALTER TABLE statement and raises ER_TABLE_DEF_CHANGED.

ALTER TABLE with DISCARD ... PARTITION ... TABLESPACE 或 IMPORT ... PARTITION ... TABLESPACE 不创建任何临时表或临时分区文件。ALTER TABLE with DISCARD ... PARTITION ... TABLESPACE or IMPORT ... PARTITION ... TABLESPACE does not create any temporary tables or temporary partition files.

ALTER TABLE 配合 ADD PARTITION、DROP PARTITION、COALESCE PARTITION、REBUILD PARTITION 或 REORGANIZE PARTITION 并不会创建临时表(除非与 NDB 表一起使用);但是,这些操作可以并且确实会创建临时分区文件。ALTER TABLE with ADD PARTITION, DROP PARTITION, COALESCE PARTITION, REBUILD PARTITION, or REORGANIZE PARTITION does not create temporary tables (except when used with NDB tables); however, these operations can and do create temporary partition files.

RANGE 或 LIST 分区的 ADD 或 DROP 操作是立即操作或几乎是即时的。HASH 或 KEY 分区的 ADD 或 COALESCE 操作会在所有分区之间复制数据,除非使用了 LINEAR HASH 或 LINEAR KEY;这实际上与创建一个新表相同,尽管 ADD 或 COALESCE 操作是逐分区执行的。REORGANIZE 操作仅复制已更改的分区,不会触动未更改的分区。ADD or DROP operations for RANGE or LIST partitions are immediate operations or nearly so. ADD or COALESCE operations for HASH or KEY partitions copy data between all partitions, unless LINEAR HASH or LINEAR KEY was used; this is effectively the same as creating a new table, although the ADD or COALESCE operation is performed partition by partition. REORGANIZE operations copy only changed partitions and do not touch unchanged ones.

对于 MyISAM 表,你可以通过将系统变量 myisam_sort_buffer_size 设置为较高的数值来加快索引重建(更改过程最慢的部分)的速度。For MyISAM tables, you can speed up index re-creation (the slowest part of the alteration process) by setting the myisam_sort_buffer_size system variable to a high value.

并发控制Concurrency Control

对于支持的 ALTER TABLE 操作,你可以使用 LOCK 子句来控制在表被更改期间的并发读写级别。为此子句指定非默认值,使你能够在更改操作期间要求一定程度的并发访问或独占访问,如果无法获得所请求的锁定级别,则操作将停止。For ALTER TABLE operations that support it, you can use the LOCK clause to control the level of concurrent reads and writes on a table while it is being altered. Specifying a non-default value for this clause enables you to require a certain amount of concurrent access or exclusivity during the alter operation, and halts the operation if the requested degree of locking is not available.

对于使用 ALGORITHM=INSTANT 的操作,只允许使用 LOCK = DEFAULT。其他 LOCK 子句参数不适用。Only LOCK = DEFAULT is permitted for operations that use ALGORITHM=INSTANT. The other LOCK clause parameters are not applicable.

LOCK 子句的参数如下:The parameters for the LOCK clause are:

  • LOCK = DEFAULT

    给定 ALGORITHM 子句(如果有)和 ALTER TABLE 操作的最大并发级别:如果支持,则允许并发读写。如果不支持,则如果支持则允许并发读取。如果仍不支持,则强制独占访问。Maximum level of concurrency for the given ALGORITHM clause (if any) and ALTER TABLE operation: Permit concurrent reads and writes if supported. If not, permit concurrent reads if supported. If not, enforce exclusive access.

  • LOCK = NONE

    如果支持,允许并发读写。否则,会发生错误。If supported, permit concurrent reads and writes. Otherwise, an error occurs.

  • LOCK = SHARED

    如果支持,允许并发读取但阻止写入。即使存储引擎对给定的 ALGORITHM 子句(如果有)和 ALTER TABLE 操作支持并发写入,也会阻止写入。如果不支持并发读取,会发生错误。If supported, permit concurrent reads but block writes. Writes are blocked even if concurrent writes are supported by the storage engine for the given ALGORITHM clause (if any) and ALTER TABLE operation. If concurrent reads are not supported, an error occurs.

  • LOCK = EXCLUSIVE

    强制独占访问。即使存储引擎对给定的 ALGORITHM 子句(如果有)和 ALTER TABLE 操作支持并发读/写,也会执行此操作。Enforce exclusive access. This is done even if concurrent reads/writes are supported by the storage engine for the given ALGORITHM clause (if any) and ALTER TABLE operation.

添加和删除列Adding and Dropping Columns

使用 ADD 向表中添加新列,使用 DROP 删除现有列。DROP col_name 是 MySQL 对标准 SQL 的扩展。Use ADD to add new columns to a table, and DROP to remove existing columns. DROP col_name is a MySQL extension to standard SQL.

要在表行中的特定位置添加列,请使用 FIRST 或 AFTER col_name。默认情况下,列会添加到最后。To add a column at a specific position within a table row, use FIRST or AFTER col_name. The default is to add the column last.

如果表只包含一列,则无法删除此列。如果您的意图是删除表,请改为使用 DROP TABLE 语句。If a table contains only one column, the column cannot be dropped. If what you intend is to remove the table, use the DROP TABLE statement instead.

如果从表中删除列,则这些列也会从它们所属的任何索引中删除。如果组成索引的所有列都被删除,索引也会被删除。如果使用 CHANGE 或 MODIFY 缩短一个存在索引的列,并且结果列的长度小于索引长度,MySQL 会自动缩短索引长度。If columns are dropped from a table, the columns are also removed from any index of which they are a part. If all columns that make up an index are dropped, the index is dropped as well. If you use CHANGE or MODIFY to shorten a column for which an index exists on the column, and the resulting column length is less than the index length, MySQL shortens the index automatically.

对于 ALTER TABLE ... ADD,如果列具有使用非确定性函数的表达式默认值,则该语句可能会生成警告或错误。有关更多信息,请参见 第 13.6 节,“数据类型默认值”,以及 第 19.1.3.7 节,“使用 GTID 的复制限制”。For ALTER TABLE ... ADD, if the column has an expression default value that uses a nondeterministic function, the statement may produce a warning or error. For further information, see Section 13.6, “Data Type Default Values”, and Section 19.1.3.7, “Restrictions on Replication with GTIDs”.

重命名、重新定义和重新排序列Renaming, Redefining, and Reordering Columns

CHANGE、MODIFY、RENAME COLUMN 和 ALTER 子句允许修改现有列的名称和定义。它们具有以下比较特点:The CHANGE, MODIFY, RENAME COLUMN, and ALTER clauses enable the names and definitions of existing columns to be altered. They have these comparative characteristics:

  • CHANGE:

    • 可以重命名列并更改其定义,或者两者都做。Can rename a column and change its definition, or both.

    • 功能比 MODIFY 或 RENAME COLUMN 更强,但在某些操作上牺牲了便利性。CHANGE 如果不重命名列,则需要对列命名两次;如果只是重命名列,则需要重新指定列定义。Has more capability than MODIFY or RENAME COLUMN, but at the expense of convenience for some operations. CHANGE requires naming the column twice if not renaming it, and requires respecifying the column definition if only renaming it.

    • 使用 FIRST 或 AFTER 可以重新排列列顺序。With FIRST or AFTER, can reorder columns.

  • MODIFY:

    • 可以更改列的定义,但不能更改其名称。Can change a column definition but not its name.

    • 比 CHANGE 更方便地修改列定义而不重命名它。More convenient than CHANGE to change a column definition without renaming it.

    • 使用 FIRST 或 AFTER 可以重新排列列顺序。With FIRST or AFTER, can reorder columns.

  • RENAME COLUMN:RENAME COLUMN:

    • 可以更改列名,但不能更改其定义。Can change a column name but not its definition.

    • 比CHANGE更方便地重命名列而不改变其定义。More convenient than CHANGE to rename a column without changing its definition.

  • ALTER:仅用于更改列的默认值。ALTER: Used only to change a column default value.

CHANGE是 MySQL 对标准 SQL 的扩展。MODIFY和RENAME COLUMN是为了兼容 Oracle 的 MySQL 扩展。CHANGE is a MySQL extension to standard SQL. MODIFY and RENAME COLUMN are MySQL extensions for Oracle compatibility.

要更改列以同时修改其名称和定义,请使用CHANGE,指定旧名称、新名称和新定义。例如,要将一个INT NOT NULL列从a重命名为b,并将其定义更改为使用BIGINT数据类型,同时保留NOT NULL属性,请执行以下操作:To alter a column to change both its name and definition, use CHANGE, specifying the old and new names and the new definition. For example, to rename an INT NOT NULL column from a to b and change its definition to use the BIGINT data type while retaining the NOT NULL attribute, do this:

ALTER TABLE t1 CHANGE a b BIGINT NOT NULL;

要更改列定义而不更改其名称,请使用CHANGE或MODIFY。使用CHANGE时,语法需要两个列名,因此若不更改名称,则必须将同一名称指定两次。例如,要更改列b的定义,请执行以下操作:To change a column definition but not its name, use CHANGE or MODIFY. With CHANGE, the syntax requires two column names, so you must specify the same name twice to leave the name unchanged. For example, to change the definition of column b, do this:

ALTER TABLE t1 CHANGE b b INT NOT NULL;

MODIFY在更改定义而不更改名称时更方便,因为仅需要一次指定列名:MODIFY is more convenient to change the definition without changing the name because it requires the column name only once:

ALTER TABLE t1 MODIFY b INT NOT NULL;

要更改列名而不更改其定义,请使用CHANGE或RENAME COLUMN。使用CHANGE时,语法要求有列定义,因此若不更改定义,则必须重新指定当前列的定义。例如,要将一个INT NOT NULL列从b重命名为a,请执行以下操作:To change a column name but not its definition, use CHANGE or RENAME COLUMN. With CHANGE, the syntax requires a column definition, so to leave the definition unchanged, you must respecify the definition the column currently has. For example, to rename an INT NOT NULL column from b to a, do this:

ALTER TABLE t1 CHANGE b a INT NOT NULL;

RENAME COLUMN在更改名称而不更改定义时更方便,因为仅需指定旧名称和新名称:RENAME COLUMN is more convenient to change the name without changing the definition because it requires only the old and new names:

ALTER TABLE t1 RENAME COLUMN b TO a;

通常情况下,不能将列重命名为表中已存在的名称。但有时并非如此,例如当你交换名称或通过循环移动名称时。如果表中有列名为a、b和c,以下操作是有效的:In general, you cannot rename a column to a name that already exists in the table. However, this is sometimes not the case, such as when you swap names or move them through a cycle. If a table has columns named a, b, and c, these are valid operations:

-- swap a and b
ALTER TABLE t1 RENAME COLUMN a TO b,
               RENAME COLUMN b TO a;
-- "rotate" a, b, c through a cycle
ALTER TABLE t1 RENAME COLUMN a TO b,
               RENAME COLUMN b TO c,
               RENAME COLUMN c TO a;

对于使用CHANGE或MODIFY进行的列定义更改,定义必须包括数据类型和所有应该应用于新列的属性,不包括索引属性,例如PRIMARY KEY或UNIQUE。原定义中存在但未在新定义中指定的属性将不会被继承。假设列col1定义为INT UNSIGNED DEFAULT 1 COMMENT 'my column',你希望仅将INT修改为BIGINT,可以这样修改:For column definition changes using CHANGE or MODIFY, the definition must include the data type and all attributes that should apply to the new column, other than index attributes such as PRIMARY KEY or UNIQUE. Attributes present in the original definition but not specified for the new definition are not carried forward. Suppose that a column col1 is defined as INT UNSIGNED DEFAULT 1 COMMENT 'my column' and you modify the column as follows, intending to change only INT to BIGINT:

ALTER TABLE t1 MODIFY col1 BIGINT;

该语句将数据类型从INT更改为BIGINT,但同时会丢失UNSIGNED、DEFAULT和COMMENT属性。要保留这些属性,必须在语句中显式包含它们:That statement changes the data type from INT to BIGINT, but it also drops the UNSIGNED, DEFAULT, and COMMENT attributes. To retain them, the statement must include them explicitly:

ALTER TABLE t1 MODIFY col1 BIGINT UNSIGNED DEFAULT 1 COMMENT 'my column';

对于使用CHANGE或MODIFY进行的数据类型更改,MySQL 会尽可能将现有列值转换为新类型。For data type changes using CHANGE or MODIFY, MySQL tries to convert existing column values to the new type as well as possible.

Warning

此转换可能会导致数据发生更改。例如,如果您缩短字符串列,值可能会被截断。为了防止在转换为新数据类型时导致数据丢失时操作仍然成功,请在使用 ALTER TABLE 之前启用严格 SQL 模式(参见 第 7.1.11 节,“服务器 SQL 模式”)。This conversion may result in alteration of data. For example, if you shorten a string column, values may be truncated. To prevent the operation from succeeding if conversions to the new data type would result in loss of data, enable strict SQL mode before using ALTER TABLE (see Section 7.1.11, “Server SQL Modes”).

如果您使用 CHANGE 或 MODIFY 缩短已建立索引的列,并且结果列的长度小于索引长度,MySQL 会自动缩短索引。If you use CHANGE or MODIFY to shorten a column for which an index exists on the column, and the resulting column length is less than the index length, MySQL shortens the index automatically.

对于通过 CHANGE 或 RENAME COLUMN 重命名的列,MySQL 会自动重命名对重命名列的以下引用:For columns renamed by CHANGE or RENAME COLUMN, MySQL automatically renames these references to the renamed column:

  • 引用旧列的索引,包括不可见索引和已禁用的 MyISAM 索引。Indexes that refer to the old column, including invisible indexes and disabled MyISAM indexes.

  • 引用旧列的外键。Foreign keys that refer to the old column.

对于通过 CHANGE 或 RENAME COLUMN 重命名的列,MySQL 不会自动重命名对该列的引用:For columns renamed by CHANGE or RENAME COLUMN, MySQL does not automatically rename these references to the renamed column:

  • 引用重命名列的生成列和分区表达式。您必须在与重命名列相同的 ALTER TABLE 语句中使用 CHANGE 来重新定义此类表达式。Generated column and partition expressions that refer to the renamed column. You must use CHANGE to redefine such expressions in the same ALTER TABLE statement as the one that renames the column.

  • 引用已重命名列的视图和存储程序。您必须手动更改这些对象的定义以引用新的列名。Views and stored programs that refer to the renamed column. You must manually alter the definition of these objects to refer to the new column name.

要重新排序表中的列,请在 CHANGE 或 MODIFY 操作中使用 FIRST 和 AFTER。To reorder columns within a table, use FIRST and AFTER in CHANGE or MODIFY operations.

ALTER ... SET DEFAULT 或 ALTER ... DROP DEFAULT 分别指定列的新默认值或删除旧的默认值。如果删除了旧的默认值且该列可以为 NULL,则新默认值为 NULL。如果该列不能为 NULL,MySQL 将根据 第 13.6 节,“数据类型默认值” 中的描述分配默认值。ALTER ... SET DEFAULT or ALTER ... DROP DEFAULT specify a new default value for a column or remove the old default value, respectively. If the old default is removed and the column can be NULL, the new default is NULL. If the column cannot be NULL, MySQL assigns a default value as described in Section 13.6, “Data Type Default Values”.

ALTER ... SET VISIBLE 和 ALTER ... SET INVISIBLE 可以更改列的可见性。参见 第 15.1.20.10 节,“不可见列”。ALTER ... SET VISIBLE and ALTER ... SET INVISIBLE enable column visibility to be changed. See Section 15.1.20.10, “Invisible Columns”.

主键和索引Primary Keys and Indexes

DROP PRIMARY KEY 删除 主键。如果没有主键,将产生错误。有关主键性能特性的详细信息,尤其是对于 InnoDB 表,请参见 第 10.3.2 节,“主键优化”。DROP PRIMARY KEY drops the primary key. If there is no primary key, an error occurs. For information about the performance characteristics of primary keys, especially for InnoDB tables, see Section 10.3.2, “Primary Key Optimization”.

如果启用了 sql_require_primary_key 系统变量,尝试删除主键将产生错误。If the sql_require_primary_key system variable is enabled, attempting to drop a primary key produces an error.

如果你向表中添加 UNIQUE INDEX 或 PRIMARY KEY,MySQL 会在任何非唯一索引之前存储它,以尽早检测重复键。If you add a UNIQUE INDEX or PRIMARY KEY to a table, MySQL stores it before any nonunique index to permit detection of duplicate keys as early as possible.

DROP INDEX 删除索引。这是对标准 SQL 的 MySQL 扩展。参见 第 15.1.27 节,“DROP INDEX 语句”。要确定索引名称,请使用 SHOW INDEX FROM tbl_name。DROP INDEX removes an index. This is a MySQL extension to standard SQL. See Section 15.1.27, “DROP INDEX Statement”. To determine index names, use SHOW INDEX FROM tbl_name.

某些存储引擎允许在创建索引时指定索引类型。index_type 的语法是 USING type_name。有关 USING 的详细信息,请参见 第 15.1.15 节,“CREATE INDEX 语句”。推荐的位置是在列列表之后。预计将在未来的 MySQL 版本中取消在列列表之前使用该选项的支持。Some storage engines permit you to specify an index type when creating an index. The syntax for the index_type specifier is USING type_name. For details about USING, see Section 15.1.15, “CREATE INDEX Statement”. The preferred position is after the column list. Expect support for use of the option before the column list to be removed in a future MySQL release.

index_option 值用于指定索引的其他选项。USING 是其中之一。有关允许的 index_option 值的详细信息,参见 第 15.1.15 节,“CREATE INDEX 语句”。index_option values specify additional options for an index. USING is one such option. For details about permissible index_option values, see Section 15.1.15, “CREATE INDEX Statement”.

RENAME INDEX old_index_name TO new_index_name 用于重命名索引。这是对标准 SQL 的 MySQL 扩展。表的内容保持不变。old_index_name 必须是表中已存在的索引名称,并且不能在同一条 ALTER TABLE 语句中被删除。new_index_name 是新的索引名称,不能与应用更改后生成表中现有的索引名称重复。两个索引名称都不能是 PRIMARY。RENAME INDEX old_index_name TO new_index_name renames an index. This is a MySQL extension to standard SQL. The content of the table remains unchanged. old_index_name must be the name of an existing index in the table that is not dropped by the same ALTER TABLE statement. new_index_name is the new index name, which cannot duplicate the name of an index in the resulting table after changes have been applied. Neither index name can be PRIMARY.

如果在 MyISAM 表上使用 ALTER TABLE,所有非唯一索引将作为单独的批次创建(类似于 REPAIR TABLE)。当索引较多时,这应当能让 ALTER TABLE 快得多。If you use ALTER TABLE on a MyISAM table, all nonunique indexes are created in a separate batch (as for REPAIR TABLE). This should make ALTER TABLE much faster when you have many indexes.

对于 MyISAM 表,可以显式控制键的更新。使用 ALTER TABLE ... DISABLE KEYS 告诉 MySQL 停止更新非唯一索引。然后使用 ALTER TABLE ... ENABLE KEYS 重新创建缺失的索引。MyISAM 使用一种特殊算法执行此操作,比逐个插入键要快得多,因此在进行大批量插入操作之前禁用键应能显著提高速度。使用 ALTER TABLE ... DISABLE KEYS 除了需要前面提到的权限外,还需要 INDEX 权限。For MyISAM tables, key updating can be controlled explicitly. Use ALTER TABLE ... DISABLE KEYS to tell MySQL to stop updating nonunique indexes. Then use ALTER TABLE ... ENABLE KEYS to re-create missing indexes. MyISAM does this with a special algorithm that is much faster than inserting keys one by one, so disabling keys before performing bulk insert operations should give a considerable speedup. Using ALTER TABLE ... DISABLE KEYS requires the INDEX privilege in addition to the privileges mentioned earlier.

当非唯一索引被禁用时,诸如 SELECT 和 EXPLAIN 等语句将忽略这些索引,否则会使用它们。While the nonunique indexes are disabled, they are ignored for statements such as SELECT and EXPLAIN that otherwise would use them.

在执行 ALTER TABLE 语句后,可能需要运行 ANALYZE TABLE 来更新索引基数信息。参见 第 15.7.7.23 节,“SHOW INDEX 语句”。After an ALTER TABLE statement, it may be necessary to run ANALYZE TABLE to update index cardinality information. See Section 15.7.7.23, “SHOW INDEX Statement”.

ALTER INDEX 操作允许将索引设为可见或不可见。不可见索引不会被优化器使用。索引可见性的修改适用于除主键(无论是显式还是隐式)之外的索引,且不能使用 ALGORITHM=INSTANT 进行。该功能与存储引擎无关(任何存储引擎均支持)。有关更多信息,请参见 第 10.3.12 节,“不可见索引”。The ALTER INDEX operation permits an index to be made visible or invisible. An invisible index is not used by the optimizer. Modification of index visibility applies to indexes other than primary keys (either explicit or implicit), and cannot be performed using ALGORITHM=INSTANT. This feature is storage engine neutral (supported for any engine). For more information, see Section 10.3.12, “Invisible Indexes”.

外键及其他约束Foreign Keys and Other Constraints

FOREIGN KEY,REFERENCES 子句由 InnoDB 和 NDB 存储引擎支持,这些引擎实现了 ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (...) REFERENCES ... (...)。参见 第 15.1.20.5 节,“FOREIGN KEY Constraints”。对于其他存储引擎,子句会被解析但忽略。The FOREIGN KEY and REFERENCES clauses are supported by the InnoDB and NDB storage engines, which implement ADD [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (...) REFERENCES ... (...). See Section 15.1.20.5, “FOREIGN KEY Constraints”. For other storage engines, the clauses are parsed but ignored.

表,如果没有任何可变长度列(ALTER TABLE忽略CREATE TABLE, ADD FOREIGN KEY如果提供,则使用自动生成的外键名称。作为解决方法,包括index_name子句以指定外键名称:CONSTRAINT更改内部生成的和用户定义的For ALTER TABLE, unlike CREATE TABLE, ADD FOREIGN KEY ignores index_name if given and uses an automatically generated foreign key name. As a workaround, include the CONSTRAINT clause to specify the foreign key name:

ADD CONSTRAINT name FOREIGN KEY (....) ...
Important

MySQL 默然忽略内联 REFERENCES 规范,其中引用是列规范的一部分。MySQL 只接受 REFERENCES 子句,定义为独立 FOREIGN KEY。MySQL silently ignores inline REFERENCES specifications, where the references are defined as part of the column specification. MySQL accepts only REFERENCES clauses defined as part of a separate FOREIGN KEY specification.

Note

分区 InnoDB 表不支持外键。该限制不适用于 NDB 表,包括那些由 [LINEAR] KEY的表。更多信息请参见 第 26.6.2 节,”与存储引擎相关的分区限制“。Partitioned InnoDB tables do not support foreign keys. This restriction does not apply to NDB tables, including those explicitly partitioned by [LINEAR] KEY. For more information, see Section 26.6.2, “Partitioning Limitations Relating to Storage Engines”.

MySQL Server 和 NDB Cluster 都支持 ALTER TABLE 来丢弃外键:MySQL Server and NDB Cluster both support the use of ALTER TABLE to drop foreign keys:

ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;

在同一个 ALTER TABLE 语句支持 ALTER TABLE ... ALGORITHM=INPLACE,但不适用于 ALTER TABLE ... ALGORITHM=COPY。Adding and dropping a foreign key in the same ALTER TABLE statement is supported for ALTER TABLE ... ALGORITHM=INPLACE but not for ALTER TABLE ... ALGORITHM=COPY.

服务器禁止更改可能导致引用完整性丢失的外键列。一种变通方法是使用 ALTER TABLE ... DROP FOREIGN KEY在更改列定义和 ALTER TABLE ... ADD FOREIGN KEY。禁止更改的示例包括:The server prohibits changes to foreign key columns that have the potential to cause loss of referential integrity. A workaround is to use ALTER TABLE ... DROP FOREIGN KEY before changing the column definition and ALTER TABLE ... ADD FOREIGN KEY afterward. Examples of prohibited changes include:

  • 对外键列的数据类型进行可能不安全的更改。例如,将VARCHAR(20)更改为VARCHAR(30)是允许的,但改为VARCHAR(1024)则不允许,因为这会改变存储单个值所需的长度字节数。Changes to the data type of foreign key columns that may be unsafe. For example, changing VARCHAR(20) to VARCHAR(30) is permitted, but changing it to VARCHAR(1024) is not because that alters the number of length bytes required to store individual values.

  • 在非严格模式下,将NULL列更改为NOT NULL是不允许的,以防止将NULL值转换为默认的非NULL值,而引用表中没有相应的值。在严格模式下,这种操作是允许的,但如果需要进行此类转换,将返回错误。Changing a NULL column to NOT NULL in non-strict mode is prohibited to prevent converting NULL values to default non-NULL values, for which there are no corresponding values in the referenced table. The operation is permitted in strict mode, but an error is returned if any such conversion is required.

ALTER TABLE tbl_name RENAME new_tbl_name会更改内部生成的外键约束名称以及以字符串“tbl_name_ibfk_”开头的用户定义外键约束名称,以反映新表名。InnoDB将以字符串“tbl_name_ibfk_”开头的外键约束名称解释为内部生成的名称。ALTER TABLE tbl_name RENAME new_tbl_name changes internally generated foreign key constraint names and user-defined foreign key constraint names that begin with the string “tbl_name_ibfk_” to reflect the new table name. InnoDB interprets foreign key constraint names that begin with the string “tbl_name_ibfk_” as internally generated names.

ALTER TABLE允许为现有表添加、删除或更改CHECK约束:ALTER TABLE permits CHECK constraints for existing tables to be added, dropped, or altered:

  • 添加新的CHECK约束:Add a new CHECK constraint:

    ALTER TABLE tbl_name
        ADD [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED];
    

    约束语法元素的含义与CREATE TABLE相同。参见第 15.1.20.6 节,“CHECK 约束”。The meaning of constraint syntax elements is the same as for CREATE TABLE. See Section 15.1.20.6, “CHECK Constraints”.

  • 删除现有名为symbol的CHECK约束:Drop an existing CHECK constraint named symbol:

    ALTER TABLE tbl_name
        DROP CHECK symbol;
    
  • 更改现有名为symbol的CHECK约束是否强制执行:Alter whether an existing CHECK constraint named symbol is enforced:

    ALTER TABLE tbl_name
        ALTER CHECK symbol [NOT] ENFORCED;
    

DROP CHECK和ALTER CHECK子句是 MySQL 对标准 SQL 的扩展。The DROP CHECK and ALTER CHECK clauses are MySQL extensions to standard SQL.

ALTER TABLE允许使用更通用(且符合 SQL 标准)的语法来删除和更改任何类型的现有约束,其中约束类型由约束名称确定:ALTER TABLE permits more general (and SQL standard) syntax for dropping and altering existing constraints of any type, where the constraint type is determined from the constraint name:

  • 删除现有名为symbol的约束:Drop an existing constraint named symbol:

    ALTER TABLE tbl_name
        DROP CONSTRAINT symbol;
    

    如果启用了 sql_require_primary_key 系统变量,尝试删除主键将产生错误。If the sql_require_primary_key system variable is enabled, attempting to drop a primary key produces an error.

  • 更改现有名为symbol的约束是否强制执行:Alter whether an existing constraint named symbol is enforced:

    ALTER TABLE tbl_name
        ALTER CONSTRAINT symbol [NOT] ENFORCED;
    

    只有CHECK约束可以更改为不强制执行。所有其他约束类型始终强制执行。Only CHECK constraints can be altered to be unenforced. All other constraint types are always enforced.

SQL 标准规定所有类型的约束(主键、唯一索引、外键、检查)都属于同一个命名空间。在 MySQL 中,每个约束类型每个模式都有自己的命名空间。因此,每种约束类型的名称必须在每个模式中唯一,但不同类型的约束名称可以相同。当多个约束名称相同时,DROP CONSTRAINT 和 ADD CONSTRAINT 是歧义的,会导致错误。在这种情况下,必须使用约束特定的语法来修改约束。例如,使用 DROP PRIMARY KEY DROP FOREIGN KEY 来删除主键或外键。The SQL standard specifies that all types of constraints (primary key, unique index, foreign key, check) belong to the same namespace. In MySQL, each constraint type has its own namespace per schema. Consequently, names for each type of constraint must be unique per schema, but constraints of different types can have the same name. When multiple constraints have the same name, DROP CONSTRAINT and ADD CONSTRAINT are ambiguous and an error occurs. In such cases, constraint-specific syntax must be used to modify the constraint. For example, use DROP PRIMARY KEY or DROP FOREIGN KEY to drop a primary key or foreign key.

如果表的修改导致强制的 CHECK 约束被违反,则发生错误,表不会被修改。发生错误的操作示例:If a table alteration causes a violation of an enforced CHECK constraint, an error occurs and the table is not modified. Examples of operations for which an error occurs:

  • 尝试在AUTO_INCREMENT。Attempts to add the AUTO_INCREMENT attribute to a column that is used in a CHECK constraint.

  • 尝试添加强制CHECK约束,或强制执行非强制CHECK约束,且现有行违反约束条件。Attempts to add an enforced CHECK constraint or enforce a nonenforced CHECK constraint for which existing rows violate the constraint condition.

  • 尝试修改、重命名或丢弃用于CHECK约束的列,除非该约束在同一语句中也被丢弃。例外:如果CHECK约束仅指代单一列,丢弃该列自动丢弃该约束。Attempts to modify, rename, or drop a column that is used in a CHECK constraint, unless that constraint is also dropped in the same statement. Exception: If a CHECK constraint refers only to a single column, dropping the column automatically drops the constraint.

ALTER TABLE tbl_name RENAME new_tbl_name以字符串CHECK constraint names that begin with the string “tbl_name开头的约束名称”以反映新的表名。MySQL 将其解释为CHECK constraint names that begin with the string “tbl_name开头的约束名称”内部生成的名称。ALTER TABLE tbl_name RENAME new_tbl_name changes internally generated and user-defined CHECK constraint names that begin with the string “tbl_name_chk_” to reflect the new table name. MySQL interprets CHECK constraint names that begin with the string “tbl_name_chk_” as internally generated names.

更改字符集Changing the Character Set

要更改表的默认字符集和所有字符列(CHAR, VARCHAR, TEXT到一个新的字符集,可以使用这样的语句: To change the table default character set and all character columns (CHAR, VARCHAR, TEXT) to a new character set, use a statement like this:

ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

该语句还会更改所有字符列的排序。如果你没有指定 COLLATE 子句来指示使用哪种排序,则该语句对字符集使用默认排序。如果这种排序不适合预期的表用途(例如,如果它会从大小写区分排序变为不区分大小写排序),则应明确指定排序。The statement also changes the collation of all character columns. If you specify no COLLATE clause to indicate which collation to use, the statement uses default collation for the character set. If this collation is inappropriate for the intended table use (for example, if it would change from a case-sensitive collation to a case-insensitive collation), specify a collation explicitly.

对于具有数据类型 VARCHAR 或其中一个 TEXT 类型,CONVERT TO CHARACTER SET需要更改数据类型,以确保新列长度足以存储与原列相同的字符数。例如,TEXT 列有两个长度字节,存储列中值的字节长度,最多可达 65,535。对于 latin1 TEXT 列,每个字符需要一个字节,因此该列最多可存储 65,535 个字符。如果将列转换为 utf8mb4,每个字符可能需要最多 4 字节,最大长度为 4 × 65,535 = 262,140 字节。该长度不适用于 TEXT 列长度字节,因此 MySQL 将数据类型转换为 MEDIUMTEXT这是长度字节能记录值 262,140 的最小字符串类型。类似地,VARCHAR 列可以转换为 MEDIUMTEXTFor a column that has a data type of VARCHAR or one of the TEXT types, CONVERT TO CHARACTER SET changes the data type as necessary to ensure that the new column is long enough to store as many characters as the original column. For example, a TEXT column has two length bytes, which store the byte-length of values in the column, up to a maximum of 65,535. For a latin1 TEXT column, each character requires a single byte, so the column can store up to 65,535 characters. If the column is converted to utf8mb4, each character might require up to 4 bytes, for a maximum possible length of 4 × 65,535 = 262,140 bytes. That length does not fit in a TEXT column's length bytes, so MySQL converts the data type to MEDIUMTEXT, which is the smallest string type for which the length bytes can record a value of 262,140. Similarly, a VARCHAR column might be converted to MEDIUMTEXT.

为避免上述类型的数据类型变化,不要使用 CONVERT TO CHARACTER SET。相反,应使用 MODIFY 来更改单个列。例如:To avoid data type changes of the type just described, do not use CONVERT TO CHARACTER SET. Instead, use MODIFY to change individual columns. For example:

ALTER TABLE t MODIFY latin1_text_col TEXT CHARACTER SET utf8mb4;
ALTER TABLE t MODIFY latin1_varchar_col VARCHAR(M) CHARACTER SET utf8mb4;

如果你指定 CONVERT TO CHARACTER SET binary,CHAR, VARCHAR, TEXT列被转换为对应的二进制字符串类型(BINARY, VARBINARY, BLOB)。这意味着列不再有字符集,后续的CONVERT TO 操作不适用于列。If you specify CONVERT TO CHARACTER SET binary, the CHAR, VARCHAR, and TEXT columns are converted to their corresponding binary string types (BINARY, VARBINARY, BLOB). This means that the columns no longer have a character set and a subsequent CONVERT TO operation does not apply to them.

If charset_name is DEFAULT在一个CONVERT TO CHARACTER SET操作中,使用由系统变量指定的字符集。character_set_database操作在原始字符集和指定字符集之间转换列值。这是If charset_name is DEFAULT in a CONVERT TO CHARACTER SET operation, the character set named by the character_set_database system variable is used.

Warning

该CONVERT TO当你在一个字符集中有列(例如在多线程系统中)但实际存储的值使用其他不兼容字符集(例如latin1)时,你想要的操作。在这种情况下,你必须对每个这样的列执行以下操作:utf8mb4这能起作用的原因是,当你转换到或从The CONVERT TO operation converts column values between the original and named character sets. This is not what you want if you have a column in one character set (like latin1) but the stored values actually use some other, incompatible character set (like utf8mb4). In this case, you have to do the following for each such column:

ALTER TABLE t1 CHANGE c1 c1 BLOB;
ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8mb4;

时,没有进行转换BLOB的非聚合列。The reason this works is that there is no conversion when you convert to or from BLOB columns.

仅要更改表的默认字符集,请使用以下语句:To change only the default character set for a table, use this statement:

ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;

单词DEFAULT为可选。默认字符集是指如果你未指定后续添加到表中的列字符集(例如,ALTER TABLE ... ADD column)。The word DEFAULT is optional. The default character set is the character set that is used if you do not specify the character set for columns that you add to a table later (for example, with ALTER TABLE ... ADD column).

When the foreign_key_checks system variable is enabled, which is the default setting, character set conversion is not permitted on tables that include a character string column used in a foreign key constraint. The workaround is to disable foreign_key_checks before performing the character set conversion. You must perform the conversion on both tables involved in the foreign key constraint before re-enabling foreign_key_checks. If you re-enable foreign_key_checks after converting only one of the tables, an ON DELETE CASCADE或者ON UPDATE CASCADE operation could corrupt data in the referencing table due to implicit conversion that occurs during these operations (Bug #45290, Bug #74816).When the foreign_key_checks system variable is enabled, which is the default setting, character set conversion is not permitted on tables that include a character string column used in a foreign key constraint. The workaround is to disable foreign_key_checks before performing the character set conversion. You must perform the conversion on both tables involved in the foreign key constraint before re-enabling foreign_key_checks. If you re-enable foreign_key_checks after converting only one of the tables, an ON DELETE CASCADE or ON UPDATE CASCADE operation could corrupt data in the referencing table due to implicit conversion that occurs during these operations (Bug #45290, Bug #74816).

导入 InnoDB 表Importing InnoDB Tables

InnoDB表 file-per-table space 可从备份或其他 MySQL 服务器实例导入,使用DISCARD TABLEPACE和IMPORT TABLESPACE子句。参见 第 17.6.1.3 节“导入 InnoDB 表”。An InnoDB table created in its own file-per-table tablespace can be imported from a backup or from another MySQL server instance using DISCARD TABLEPACE and IMPORT TABLESPACE clauses. See Section 17.6.1.3, “Importing InnoDB Tables”.

MyISAM 表Row Order for MyISAM Tables

ORDER BY 允许你创建新的表,并按特定顺序排列行。这个选项主要适用于你大多数时候以特定顺序查询行的情况。在表格发生重大变化后使用这个选项,你可能能获得更高的性能。在某些情况下,如果表格按你想以后排序的列顺序排列,MySQL 的排序可能会更方便。ORDER BY enables you to create the new table with the rows in a specific order. This option is useful primarily when you know that you query the rows in a certain order most of the time. By using this option after major changes to the table, you might be able to get higher performance. In some cases, it might make sorting easier for MySQL if the table is in order by the column that you want to order it by later.

Note

在插入和删除操作后,表不会保持指定的顺序。The table does not remain in the specified order after inserts and deletes.

ORDER BY 语法允许指定一个或多个列名进行排序,每个列名后可选择跟 ASC 或 DESC,分别表示排序顺序的升或降排序。默认排序顺序为升序。仅允许列名作为排序条件;不允许任意表达式。该条款应置于其他从句之后的最后。ORDER BY syntax permits one or more column names to be specified for sorting, each of which optionally can be followed by ASC or DESC to indicate ascending or descending sort order, respectively. The default is ascending order. Only column names are permitted as sort criteria; arbitrary expressions are not permitted. This clause should be given last after any other clauses.

ORDER BY 对于 InnoDB,因为 InnoDB 总是按照 clustered index)来排序表行。ORDER BY does not make sense for InnoDB tables because InnoDB always orders table rows according to the clustered index.

当用于分区表时,ALTER TABLE ... ORDER BY 仅在每个分区内排序行。When used on a partitioned table, ALTER TABLE ... ORDER BY orders rows within each partition only.

的行顺序Partitioning OptionsPartitioning Options

partition_options表示可以与分区表一起使用的选项,用于重新分区、添加、删除、丢弃、导入、合并和拆分分区,以及执行分区维护。partition_options signifies options that can be used with partitioned tables for repartitioning, to add, drop, discard, import, merge, and split partitions, and to perform partitioning maintenance.

It is possible for an ALTER TABLE statement to contain a PARTITION BY或者REMOVE PARTITIONING clause in an addition to other alter specifications, but the PARTITION BY或者REMOVE PARTITIONING clause must be specified last after any other specifications. The ADD PARTITION, DROP PARTITION, DISCARD PARTITION, IMPORT PARTITION, COALESCE PARTITION, REORGANIZE PARTITION, EXCHANGE PARTITION, ANALYZE PARTITION, CHECK PARTITION,以及REPAIR PARTITION options cannot be combined with other alter specifications in a single ALTER TABLE, since the options just listed act on individual partitions.It is possible for an ALTER TABLE statement to contain a PARTITION BY or REMOVE PARTITIONING clause in an addition to other alter specifications, but the PARTITION BY or REMOVE PARTITIONING clause must be specified last after any other specifications. The ADD PARTITION, DROP PARTITION, DISCARD PARTITION, IMPORT PARTITION, COALESCE PARTITION, REORGANIZE PARTITION, EXCHANGE PARTITION, ANALYZE PARTITION, CHECK PARTITION, and REPAIR PARTITION options cannot be combined with other alter specifications in a single ALTER TABLE, since the options just listed act on individual partitions.

关于分区选项的更多信息,请参见 第 15.1.20 节,“CREATE TABLE Statement”,以及 第 15.1.9.1 节,“ALTER TABLE Partition Operations”。关于 ALTER TABLE ... EXCHANGE PARTITION 语句,参见 第 26.3.3 节,“与表交换分区和子分区”。For more information about partition options, see Section 15.1.20, “CREATE TABLE Statement”, and Section 15.1.9.1, “ALTER TABLE Partition Operations”. For information about and examples of ALTER TABLE ... EXCHANGE PARTITION statements, see Section 26.3.3, “Exchanging Partitions and Subpartitions with Tables”.