Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  CREATE TABLE Statement

15.1.20 CREATE TABLE 语句

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    (create_definition,...)
    [table_options]
    [partition_options]

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options]
    [partition_options]
    [IGNORE | REPLACE]
    [AS] query_expression

CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
    { LIKE old_tbl_name | (LIKE old_tbl_name) }

create_definition: {
    col_name column_definition
  | {INDEX | KEY} [index_name] [index_type] (key_part,...)
      [index_option] ...
  | {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name] (key_part,...)
      [index_option] ...
  | [CONSTRAINT [symbol]] PRIMARY KEY
      [index_type] (key_part,...)
      [index_option] ...
  | [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY]
      [index_name] [index_type] (key_part,...)
      [index_option] ...
  | [CONSTRAINT [symbol]] FOREIGN KEY
      [index_name] (col_name,...)
      reference_definition
  | check_constraint_definition
}

column_definition: {
    data_type [NOT NULL | NULL] [DEFAULT {literal | (expr)} ]
      [VISIBLE | INVISIBLE]
      [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY]
      [COMMENT 'string']
      [COLLATE collation_name]
      [COLUMN_FORMAT {FIXED | DYNAMIC | DEFAULT}]
      [ENGINE_ATTRIBUTE [=] 'string']
      [SECONDARY_ENGINE_ATTRIBUTE [=] 'string']
      [STORAGE {DISK | MEMORY}]
      [reference_definition]
      [check_constraint_definition]
  | data_type
      [COLLATE collation_name]
      [GENERATED ALWAYS] AS (expr)
      [VIRTUAL | STORED] [NOT NULL | NULL]
      [VISIBLE | INVISIBLE]
      [UNIQUE [KEY]] [[PRIMARY] KEY]
      [COMMENT 'string']
      [reference_definition]
      [check_constraint_definition]
}

data_type:
    (see Chapter 13, Data Types)

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}
  |ENGINE_ATTRIBUTE [=] 'string'
  |SECONDARY_ENGINE_ATTRIBUTE [=] 'string'
}

check_constraint_definition:
    [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]

reference_definition:
    REFERENCES tbl_name (key_part,...)
      [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE]
      [ON DELETE reference_option]
      [ON UPDATE reference_option]

reference_option:
    RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

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}
  | START TRANSACTION 
  | SECONDARY_ENGINE_ATTRIBUTE [=] 'string'
  | STATS_AUTO_RECALC [=] {DEFAULT | 0 | 1}
  | STATS_PERSISTENT [=] {DEFAULT | 0 | 1}
  | STATS_SAMPLE_PAGES [=] value
  | tablespace_option
  | UNION [=] (tbl_name[,tbl_name]...)
}

partition_options:
    PARTITION BY
        { [LINEAR] HASH(expr)
        | [LINEAR] KEY [ALGORITHM={1 | 2}] (column_list)
        | RANGE{(expr) | COLUMNS(column_list)}
        | LIST{(expr) | COLUMNS(column_list)} }
    [PARTITIONS num]
    [SUBPARTITION BY
        { [LINEAR] HASH(expr)
        | [LINEAR] KEY [ALGORITHM={1 | 2}] (column_list) }
      [SUBPARTITIONS num]
    ]
    [(partition_definition [, partition_definition] ...)]

partition_definition:
    PARTITION partition_name
        [VALUES
            {LESS THAN {(expr | value_list) | MAXVALUE}
            |
            IN (value_list)}]
        [[STORAGE] ENGINE [=] engine_name]
        [COMMENT [=] 'string' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] tablespace_name]
        [(subpartition_definition [, subpartition_definition] ...)]

subpartition_definition:
    SUBPARTITION logical_name
        [[STORAGE] ENGINE [=] engine_name]
        [COMMENT [=] 'string' ]
        [DATA DIRECTORY [=] 'data_dir']
        [INDEX DIRECTORY [=] 'index_dir']
        [MAX_ROWS [=] max_number_of_rows]
        [MIN_ROWS [=] min_number_of_rows]
        [TABLESPACE [=] tablespace_name]

tablespace_option:
    TABLESPACE tablespace_name [STORAGE DISK]
  | [TABLESPACE tablespace_name] STORAGE MEMORY

query_expression:
    SELECT ...   (Some valid select or union statement)

CREATE TABLE 创建一个名为给定的表。你必须拥有该表的CREATE特权。

默认情况下,表将在默认数据库中创建,使用InnoDB存储引擎。如果表已经存在、没有默认数据库或数据库不存在,将出现错误。

MySQL 没有对表的数量限制。底层文件系统可能对表示表的文件数量施加限制,个别存储引擎也可能施加特定的约束。InnoDB 允许创建至多4亿张表。

关于表的物理表示形式,请参阅第15.1.20.1节,“CREATE TABLE语句生成文件”

CREATE TABLE 语句有多个方面,以下各个主题在本节中进行描述:

  • tbl_name

    可以将表名指定为 db_name.tbl_name,在特定的数据库中创建表。无论是否有默认数据库,假设该数据库存在。如果使用标识符,请单独引用数据库和表名。例如,写作 `mydb`.`mytbl`,而不是 `mydb.mytbl`

    关于允许的表名规则在第11.2节,“Schema Object Names”中给出。

  • IF NOT EXISTS

    如果表存在,不会发生错误。然而,不存在验证该表结构与CREATE TABLE语句所示的结构。

Temporary 表

可以在创建表时使用TEMPORARY关键字。临时表只在当前会话中可见,会话关闭时自动删除。更多信息请参阅第15.1.20.2节,“CREATE TEMPORARY TABLE Statement”

Column 数据类型 and Attributes

每个表的硬限制为4096列,但实际最大值取决于第10.4.7节,“表列数和行大小限制”中讨论的因素。

  • data_type

    data_type 表示列定义中的数据类型。关于指定列数据类型的语法描述,以及每种类型的属性信息,请见第13章,数据类型

    • AUTO_INCREMENT 只适用于整数类型。

    • 字符数据类型(CHARVARCHARTEXT 类型、ENUMSET 和任何同义词)可以包括 CHARACTER SET 来指定列的字符集。CHARSETCHARACTER SET 的同义词,可以使用 COLLATE 属性,along with any other attributes。详细信息,请见第12章,字符集、排序规则、Unicode。示例:

      CREATE TABLE t (c CHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin);

      MySQL 8.4 在字符列定义中解释长度 specifications,以字符为单位。对BINARYVARBINARY 的长度是以字节为单位。

    • 对于 CHAR, VARCHAR, BINARY, 和 VARBINARY 列,可以创建使用列值前缀的索引,使用 col_name(length) 语法指定索引前缀长度。 BLOBTEXT 列也可以索引,但是必须指定前缀长度。前缀长度对于非二进制字符串类型是以字符为单位,对于二进制字符串类型是以字节为单位。也就是说,索引条目由每个列值的第一个 length 个字符组成对于 CHAR, VARCHAR, 和 TEXT 列,和每个列值的第一个 length 个字节组成对于 BINARY, VARBINARY, 和 BLOB 列。只索引列值的前缀可以使索引文件变得非常小。关于索引前缀的更多信息,请参见 第15.1.15节,“CREATE INDEX 语句”

      只有InnoDBMyISAM存储引擎支持在BLOBTEXT列上建立索引。例如:

      CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

      如果指定的索引前缀超过最大列数据类型大小,CREATE TABLE将索引处理如下:

      • 对于非唯一索引,如果严格SQL模式启用,出现错误;否则,索引长度被减少以在最大列数据类型大小内,并产生警告(如果严格SQL模式未启用)。

      • 对于唯一索引,无论SQL模式如何,总是出现错误,因为减少索引长度可能使得不满足指定唯一性要求的记录被插入。

    • JSON列不能建立索引。您可以通过创建一个生成列,提取JSON列中的标量值来绕过这个限制。见使用生成列提供JSON列索引,了解详细示例。

  • NOT NULL | NULL

    如果既不指定NULL也未指定NOT NULL,则该列被视为指定了NULL

    MySQL 8.4 中,只有 InnoDBMyISAMMEMORY 存储引擎支持在可以包含 NULL 值的列上创建索引。在其他情况下,您必须将索引列声明为 NOT NULL,否则会出现错误。

  • DEFAULT

    指定一个列的默认值。关于默认值处理的更多信息,包括列定义中不包含明确 DEFAULT 值的情况,请参见第13.6节,“数据类型默认值”

    如果启用了 NO_ZERO_DATENO_ZERO_IN_DATE SQL 模式,并且日期默认值不符合该模式,CREATE TABLE 在非严格 SQL 模式下产生警告,在严格模式下产生错误。例如,启用 NO_ZERO_IN_DATEc1 DATE DEFAULT '2010-00-00' 产生警告。

  • VISIBLE, INVISIBLE

    指定列可见性。缺省情况下是 VISIBLE,如果不 presente 任何关键字。表至少需要有一个可见的列。尝试使所有列不可见将产生错误。更多信息,请参见第15.1.20.10节,“不可见列”

  • AUTO_INCREMENT

    整数列可以拥有额外的属性AUTO_INCREMENT。当你将NULL(推荐)或0插入到索引的AUTO_INCREMENT列中,列将被设置为表中的下一个序列值。通常,这个值是value+1value是当前表中的最大值。AUTO_INCREMENT序列从1开始。

    要在插入行后检索AUTO_INCREMENT值,可以使用LAST_INSERT_ID() SQL 函数或mysql_insert_id() C API 函数。见第14.15节,“信息函数”,和mysql_insert_id()

    如果启用了NO_AUTO_VALUE_ON_ZERO SQL 模式,你可以将0存储到AUTO_INCREMENT列中,而不生成新的序列值。见第7.1.11节,“服务器SQL模式”

    每个表只能有一个AUTO_INCREMENT列,它必须索引,并且不能有默认值。AUTO_INCREMENT列只有在包含正整数时才能正常工作。插入负数被视为插入非常大的正整数。这是为了避免精度问题,当正整数“wrap”到负整数时,也是为了确保不意外地获取AUTO_INCREMENT列包含0的值。

    对于MyISAM表,您可以在多列键中指定一个AUTO_INCREMENT次要列。见第5.6.9节,“使用 AUTO_INCREMENT”

    为了使 MySQL 兼容一些 ODBC 应用程序,您可以使用以下查询找到最后插入行的AUTO_INCREMENT值:

    SELECT * FROM tbl_name WHERE auto_col IS NULL

    这个方法要求sql_auto_is_null变量不设置为 0。见第7.1.8节,“服务器系统变量”

    关于 InnoDBAUTO_INCREMENT,请参阅第17.6.1.6节,“InnoDB 中的 AUTO_INCREMENT 处理”。关于 AUTO_INCREMENT 和 MySQL 复制,请参阅第19.5.1.1节,“MySQL 复制和 AUTO_INCREMENT”

  • COMMENT

    可以使用 COMMENT 选项指定一个列的注释,长度不超过1024个字符。该注释将被SHOW CREATE TABLESHOW FULL COLUMNS 语句显示。它也将在信息架构COLUMNS 表的 COLUMN_COMMENT 列中显示。

  • COLUMN_FORMAT

    在 NDB 集群中,也可以使用 COLUMN_FORMATNDB 表的单个列指定数据存储格式。允许的列格式是 FIXEDDYNAMICDEFAULTFIXED 用于指定固定宽度存储,DYNAMIC 允许列的宽度变动,而 DEFAULT 则使列使用数据类型确定的固定或变动宽度(可能被ROW_FORMAT 指定的override)。

    对于NDB 表,COLUMN_FORMAT 的默认值是 FIXED

    在 NDB 集群中,使用 COLUMN_FORMAT=FIXED 定义的列的最大可能偏移量为 8188 字节。更多信息和可能的解决方案,请参见第25.2.7.5 节,“NDB 集群中数据库对象相关限制”

    COLUMN_FORMAT 目前对除NDB 存储引擎外的表无效。 MySQL 8.4 会忽略 COLUMN_FORMAT

  • ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 选项用于指定主和副存储引擎的列属性。这些选项保留供将来使用。

    分配给这个选项的值是一个有效的 JSON 文档字符串或空字符串 ('')。无效的 JSON 将被拒绝。

    CREATE TABLE t1 (c1 INT ENGINE_ATTRIBUTE='{"key":"value"}');

    ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值可以重复使用,不会出现错误。在这种情况下,最后指定的值将被使用。

    ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值不由服务器检查,也不会在表存储引擎更改时清除。

  • 对于NDB 表,使用 STORAGE 子句可以指定列是否存储在磁盘或内存中。STORAGE DISK 将使列存储在磁盘上,而 STORAGE MEMORY 则使用内存存储。CREATE TABLE 语句仍然需要包含 TABLESPACE 子句:

    mysql> CREATE TABLE t1 (
        ->     c1 INT STORAGE DISK,
        ->     c2 INT STORAGE MEMORY
        -> ) ENGINE NDB;
    ERROR 1005 (HY000): Can't create table 'c.t1' (errno: 140)
    
    mysql> CREATE TABLE t1 (
        ->     c1 INT STORAGE DISK,
        ->     c2 INT STORAGE MEMORY
        -> ) TABLESPACE ts_1 ENGINE NDB;
    Query OK, 0 rows affected (1.06 sec)

    对于NDB 表,STORAGE DEFAULT 等同于 STORAGE MEMORY

    STORAGE子句对除NDB之外的存储引擎无效。STORAGE关键字仅在NDB集群提供的mysqld中支持,在其他版本的MySQL中任何尝试使用STORAGE关键字都会导致语法错误。

  • GENERATED ALWAYS

    用于指定生成列表达式。关于生成列,请参阅第15.1.20.8节,“CREATE TABLE 和 生成列”

    存储生成列可以被索引。InnoDB支持虚拟生成列的次要索引。请参阅第15.1.20.9节,“次要索引 和 生成列”

Indexes, Foreign Keys, and CHECK 约束

几个关键字适用于索引、外键和CHECK约束的创建。关于以下描述的背景信息,见第15.1.15节,“CREATE INDEX 语句”第15.1.20.5节,“外键约束”第15.1.20.6节,“CHECK 约束”

  • CONSTRAINT symbol

    CONSTRAINT symbol子句可以用来命名约束。如果不给出该子句,或者在CONSTRAINT关键字后面不包括symbol,MySQL将自动生成约束名称,以下例外。使用的symbol值必须在每个模式(数据库)中唯一,同一类型的约束也必须唯一。如果出现重复的symbol将导致错误。见第11.2.1节,“标识符长度限制”的讨论。

    Note

    如果在外键定义中不给出CONSTRAINT symbol子句,或者在CONSTRAINT关键字后面不包括symbol,MySQL将自动生成约束名称。

    SQL标准规定所有约束类型(主键、唯一索引、外键、检查约束)属于同一个命名空间。在 MySQL 中,每种约束类型都有自己的命名空间。因此,各类约束的名称必须在每个模式中唯一,但不同类型的约束可以拥有相同的名称。

  • PRIMARY KEY

    所有关键列都必须定义为NOT NULL。如果它们没有被明确地声明为NOT NULL,MySQL 会隐式地将其声明为NOT NULL(并且是静默的)。一个表只能有一个PRIMARY KEY。一个PRIMARY KEY 的名称总是PRIMARY,因此不能用作其他类型索引的名称。

    如果你没有PRIMARY KEY,应用程序请求你的表中的PRIMARY KEY,MySQL 将返回第一个没有NULL 列的唯一索引作为PRIMARY KEY

    InnoDB 表中,保持PRIMARY KEY 短,以减少次要索引的存储开销。每个次要索引条目都包含对应行的主键列的副本。(见第17.6.2.1节,“聚簇和次要索引”。)

    在创建的表中,PRIMARY KEY 首先出现,然后是所有UNIQUE 索引,最后是非唯一索引。这有助于 MySQL 优化器确定使用哪个索引,并且更快地检测重复的UNIQUE 键。

    一个PRIMARY KEY可以是一个多列索引。然而,您不能使用PRIMARY KEY关键字在列定义中创建多列索引。这样只标记单个列为主键。您必须使用独立的PRIMARY KEY(key_part, ...)子句。

    如果表有一个PRIMARY KEYUNIQUE NOT NULL索引,其中包含单个整数类型的列,您可以在SELECT语句中使用_rowid引用索引列,如唯一索引中所述。

    在 MySQL 中,一个PRIMARY KEY的名称是PRIMARY。对于其他索引,如果您不指定名称,索引将被赋予第一个索引列的名称,带有可选的后缀(_2_3...)以使其唯一。您可以使用SHOW INDEX FROM tbl_name查看索引名称,见第15.7.7.23节,“SHOW INDEX 语句”

  • KEY | INDEX

    KEY通常是INDEX的同义词。关键字PRIMARY KEY也可以在列定义中指定为只KEY,这实现了与其他数据库系统的兼容性。

  • UNIQUE

    一个 UNIQUE 索引创建了约束,使得索引中的所有值都必须是唯一的。如果您尝试添加一个与现有行匹配的新行,会出现错误。对于所有引擎,UNIQUE 索引允许多个 NULL 值在可以包含 NULL 的列中。如果您为某一列在 UNIQUE 索引指定前缀值,那么该列的值必须在前缀长度内唯一。

    如果表有一个 PRIMARY KEYUNIQUE NOT NULL 索引,其中包含单个整数类型的列,您可以使用 _rowidSELECT 语句中引用索引列,如第唯一索引 中所述。

  • FULLTEXT

    A 全文索引 是一种用于全文搜索的特殊类型索引。只有 InnoDBMyISAM 存储引擎支持 全文索引。它们只能从 CHAR, VARCHAR, 和 TEXT 列创建。索引总是对整个列进行,前缀索引不支持,如果指定了前缀长度将被忽略。见 第14.9节,“全文搜索函数”,了解操作的详细信息。可以使用 WITH PARSER 子句作为 索引选项 值,关联一个解析器插件,以便在全文索引和搜索操作中进行特殊处理。这一子句只对 FULLTEXT 索引有效。 InnoDBMyISAM 支持全文解析器插件。见全文搜索解析器插件编写全文搜索解析器插件获取更多信息。

  • SPATIAL

    您可以在空间数据类型上创建 SPATIAL 索引。空间类型仅支持在 InnoDBMyISAM 表中,且索引列必须声明为 NOT NULL。请参阅第13.4节,“空间数据类型”

  • FOREIGN KEY

    MySQL 支持外键,允许您跨表引用相关数据,并且外键约束帮助保持这些分散的数据一致。对于定义和选项信息,请参阅reference_definition,和reference_option

    使用InnoDB存储引擎的分区表不支持外键。请参阅第26.6节,“分区限制和限制”,了解更多信息。

  • CHECK

    The CHECK 子句启用了对表行数据值的约束检查。请参阅第15.1.20.6节,“CHECK约束”

  • key_part

    • 一个key_part 指定可以以ASCDESC结尾,指定索引值是否以升序或降序存储。如果不指定顺序specifier,默认是升序。

    • 前缀,通过length属性定义,可以长达767个字节,对于使用REDUNDANTCOMPACT行格式的InnoDB表。对于使用DYNAMICCOMPRESSED行格式的InnoDB表,前缀长度限制为3072个字节。对于MyISAM表,前缀长度限制为1000个字节。

      前缀limits以字节为单位。然而,在CREATE TABLEALTER TABLECREATE INDEX语句中的索引指定的前缀长度,对于非二进制字符串类型(CHARVARCHARTEXT)被解释为字符数,对于二进制字符串类型(BINARYVARBINARYBLOB)被解释为字节数。考虑到非二进制字符串列使用多字节字符集时指定前缀长度。

    • key_part 指定可以以形式(CAST json_path AS type ARRAY) 创建多值索引,用于JSON 列。关于多值索引的创建、使用、限制和限制,请参阅Multi-Valued Indexes

  • index_type

    某些存储引擎允许在创建索引时指定索引类型。index_type 指定语法为 USING type_name

    示例:

    CREATE TABLE lookup
      (id INT, INDEX USING BTREE (id)
    ) ENGINE = MEMORY;

    推荐在索引列列表后使用USING。虽然可以在列列表前使用,但该选项的支持将来可能会被删除,建议在未来 MySQL 版本中不要使用。

  • index_option

    index_option 值指定索引的额外选项。

    • KEY_BLOCK_SIZE

      对于MyISAM表,KEY_BLOCK_SIZE可选地指定索引键块的大小,以字节为单位。该值被视为提示;如果必要,可以使用不同的大小。单个索引定义中的KEY_BLOCK_SIZE值将覆盖表级别的KEY_BLOCK_SIZE值。

      关于表级别KEY_BLOCK_SIZE属性,请参阅表选项

    • WITH PARSER

      只有在使用InnoDBMyISAM时,WITH PARSER选项才能使用。它将索引与解析器插件关联,如果需要特殊处理全文检索操作。MyISAM表具有关联的全文解析器插件,可以使用InnoDB将表转换。

    • WITH PARSER

      索引定义可以包含可选的1024个字符以内的注释。

      可以使用InnoDBMERGE_THRESHOLD值来为单个索引设置一个个体的值,使用index_optionCOMMENT子句。见第17.8.11节,“配置索引页合并阈值”.

    • VISIBLE, INVISIBLE

      指定索引可见性。索引默认可见。不可见的索引不被优化器使用。索引可见性的指定适用于除主键(显式或隐式)以外的所有索引。更多信息,见第10.3.12节,“不可见索引”.

    • ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE选项用于指定主键和次要存储引擎的索引属性。这些选项保留供将来使用。

    关于可允许的index_option值的更多信息,见第15.1.15节,“CREATE INDEX 语句”。关于索引的更多信息,见第10.3.1节,“MySQL 使用索引”.

  • reference_definition

    关于reference_definition语法细节和示例,见第15.1.20.5节,“FOREIGN KEY Constraints”.

    InnoDBNDB表支持外键约束检查。被引用表的列必须总是显式命名。外键同时支持ON DELETEON UPDATE操作。更多详细信息和示例,见第15.1.20.5节,“FOREIGN KEY Constraints”.

    对于其他存储引擎,MySQL Server 解析并忽略CREATE TABLE语句中的FOREIGN KEY语法。

    Important

    对于熟悉ANSI/ISO SQL标准的用户,请注意,没有存储引擎,包括InnoDB, 认识或强制执行引用完整性约束定义中的MATCH子句。使用明确的MATCH子句不具有指定效果,并且也会忽略ON DELETEON UPDATE子句。因此,指定MATCH应该避免。

    SQL标准中的MATCH子句控制多列外键在比较主键时处理NULL值的方式。InnoDB实际实现了MATCH SIMPLE语义,允许外键完全或部分为NULL。在这种情况下,包含该外键的子表行可以插入,并且不匹配父表中的任何行。使用触发器也可以实现其他语义。

    此外,MySQL要求被引用列索引以提高性能。但是,InnoDB不强制要求被引用列声明为UNIQUENOT NULL。非唯一键或包含NULL值的外键参考在操作UPDATEDELETE CASCADE时处理不确定。你被建议使用只引用唯一键(或主键)且NOT NULL的外键。

    MySQL解析但忽略SQL标准中的“inline REFERENCES specifications”(在列规范中定义),MySQL只接受独立的FOREIGN KEY规范中的REFERENCES子句。更多信息,请参见第1.7.2.3节,“FOREIGN KEY Constraint Differences”

  • reference_option

    关于RESTRICTCASCADESET NULLNO ACTIONSET DEFAULT 选项,请参阅第15.1.20.5节,“FOREIGN KEY Constraints”.

表选项用于优化表的行为。通常情况下,不需要指定任何选项。这些建议都适用于除非另有指明的存储引擎。如果某个存储引擎不支持某个选项,可能会被接受并记忆为表定义的一部分。这样,如果后续使用ALTER TABLE将表转换到使用不同的存储引擎,这些建议也会生效。

  • ENGINE

    指定表的存储引擎,使用以下表格中的名称。引擎名称可以不加引号或加引号。加引号的名称'DEFAULT'被识别但忽略。

    Storage Engine Description
    InnoDB 事务安全表,支持行锁定和外键。新建表的默认存储引擎。见第17章,《The InnoDB Storage Engine》,特别是第17.1节,“InnoDB 简介”,如果您有 MySQL 经验但对InnoDB不熟悉。
    MyISAM 主要用于只读或读多写的工作负载的二进制可移植存储引擎。见第18.2节,“MyISAM存储引擎”
    MEMORY 该存储引擎的数据只存储在内存中。见第18.3节,“MEMORY存储引擎”
    CSV 以逗号分隔值格式存储行的表格。见第18.4节,“CSV存储引擎”
    ARCHIVE 归档存储引擎。见第18.5节,“ARCHIVE存储引擎”
    EXAMPLE 示例引擎。见第18.9节,“EXAMPLE存储引擎”
    FEDERATED 访问远程表的存储引擎。见第18.8节,“FEDERATED存储引擎”
    HEAP 这是MEMORY的同义词。
    MERGE 一个MyISAM表的集合,也称为MRG_MyISAM。见第18.7节,“MERGE存储引擎”
    NDB 集群化、容错性强、基于内存的表,支持事务和外键。也称为NDBCLUSTER。见第25章,《MySQL NDB集群 8.4》

    默认情况下,如果指定的存储引擎不可用,语句将以错误结束。您可以通过从服务器SQL模式中删除NO_ENGINE_SUBSTITUTION来覆盖这个行为,以便MySQL允许将指定的引擎替换为默认存储引擎,而不是失败。通常情况下,这个默认值是InnoDBdefault_storage_engine系统变量的默认值。在NO_ENGINE_SUBSTITUTION被禁用时,如果存储引擎指定不被尊重,会出现警告。

  • AUTOEXTEND_SIZE

    定义了 InnoDB 当表空间满时扩展的大小。设置必须是4MB的倍数。默认设置为0,导致表空间根据隐式默认行为来扩展。更多信息,请参见第17.6.3.9节,“Tablespace AUTOEXTEND_SIZE 配置”

  • AUTO_INCREMENT

    表的初始 AUTO_INCREMENT 值。在 MySQL 8.4 中,这个值适用于 MyISAMMEMORYInnoDBARCHIVE 表。对于不支持 AUTO_INCREMENT 表选项的引擎,可以在创建表后插入一个值小于所需值的一行“dummy”行,然后删除该行。

    对于支持 AUTO_INCREMENT 表选项的引擎,在CREATE TABLE 语句中,也可以使用 ALTER TABLE tbl_name AUTO_INCREMENT = N 重置 AUTO_INCREMENT 值。该值不能小于当前列中的最大值。

  • AVG_ROW_LENGTH

    表的平均行长近似值。您需要为变长行的大表设置这个值。

    当您创建一个MyISAM表时,MySQL 使用MAX_ROWSAVG_ROW_LENGTH选项来决定结果表的大小。如果您不指定任何选项,MyISAM数据和索引文件的最大大小默认为256TB(如果您的操作系统不支持这么大的文件,那么表大小将被限制于文件大小限制)。如果您想减少指针大小以使索引更小更快,并且不需要太大文件,可以通过设置myisam_data_pointer_size系统变量来降低默认指针大小。 (参见第7.1.8节,“服务器系统变量”。)如果您想让所有表都可以超出默认限制,并且愿意让表慢一些大一些,可以增加这个变量的值。将该值设置为7,允许表大小达到65,536TB。

  • [DEFAULT] CHARACTER SET

    指定表的默认字符集。CHARSETCHARACTER SET的同义词。如果字符集名称为DEFAULT

  • CHECKSUM

    将其设置为 1,如果您想要 MySQL 实时维护表中的所有行的live checksum(即 MySQL 自动更新 checksum,因为表结构变化)。这使得表更新速度慢一点,但也更容易找到损坏的表。CHECKSUM TABLE 语句报告checksum。(MyISAM 只有。)

  • [DEFAULT] COLLATE

    指定表的默认排序规则。

  • COMMENT

    表的注释,长达 2048 个字符。

    您可以使用 table_option COMMENT 子句来设置 InnoDB 表的 MERGE_THRESHOLD 值。见第 17.8.11 节,“索引页合并阈值配置”

    设置 NDB 表选项。 创建一个 CREATE TABLE 语句或ALTER TABLE 语句,可以使用表注释来指定一个到四个 NDB_TABLE 选项,例如 NOLOGGINGREAD_BACKUPPARTITION_BALANCEFULLY_REPLICATED,作为名称-值对,使用逗号分隔,如果需要,可以在字符串 NDB_TABLE= 之后立即跟随。以下是一个使用该语法的示例语句:

    CREATE TABLE t1 (
        c1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
        c2 VARCHAR(100),
        c3 VARCHAR(100) )
    ENGINE=NDB
    COMMENT="NDB_TABLE=READ_BACKUP=0,PARTITION_BALANCE=FOR_RP_BY_NODE";

    不允许在引号字符串中出现空格。字符串是大小写不敏感。

    表注释将作为SHOW CREATE TABLE 的输出的一部分。注释的文本也可以在 MySQL 信息架构 TABLES 表中的 TABLE_COMMENT 列中找到。

    该注释语法也支持ALTER TABLE 语句对 NDB 表。请注意,使用 ALTER TABLE 语句时,表注释将替换之前的任何注释。

    NDB表中,设置MERGE_THRESHOLD选项在表注释中不受支持(被忽略)。

    完整语法信息和示例,请见第15.1.20.12节,“设置NDB注释选项”

  • 压缩

    用于文件-per-table表空间中的InnoDB表的页面级别压缩算法。支持的值包括ZlibLZ4None压缩属性是透明页面压缩特性的引入。页面压缩仅支持在文件-per-table表空间中的InnoDB表,并且仅在支持稀疏文件和洞穿的Linux和Windows平台上可用。更多信息,请见第17.9.2节,“InnoDB页面压缩”

  • 连接

    一个FEDERATED表的连接字符串。

    Note

    更早版本的MySQL使用注释选项来指定连接字符串。

  • 数据目录索引目录

    对于InnoDBDATA DIRECTORY='directory'子句允许在数据目录外创建表。必须启用innodb_file_per_table变量以使用DATA DIRECTORY子句。完整的目录路径必须指定,并且已知于InnoDB。更多信息,请参见第17.6.1.2节,“外部创建表”

    当创建MyISAM表时,可以使用DATA DIRECTORY='directory'子句、INDEX DIRECTORY='directory'子句,或者两者都可以。它们分别指定了MyISAM表的数据文件和索引文件所在目录。与InnoDB表不同,MySQL 在创建MyISAM表时,不会根据数据库名称创建子目录。文件将被创建在指定的目录中。

    您必须拥有FILE特权以使用DATA DIRECTORYINDEX DIRECTORY表选项。

    Important

    表级别的DATA DIRECTORYINDEX DIRECTORY选项对分区表无效。(BUG #32091)

    这些选项只有在不使用--skip-symbolic-links选项时才能生效。您的操作系统也必须具有工作的、线程安全的realpath()调用。见第10.12.2.2节,“Unix上使用符号链接来管理MyISAM表”,获取更多信息。

    如果使用MyISAM创建一个没有指定DATA DIRECTORY选项的表,创建的.MYD文件将在数据库目录中创建。默认情况下,如果在这种情况下找到现有.MYD文件,MyISAM将覆盖它。同样,对于没有指定INDEX DIRECTORY选项的表,创建的.MYI文件也会被覆盖。要抑制这种行为,可以使用--keep_files_on_create选项,在这种情况下,MyISAM不会覆盖文件而是返回错误。

    如果使用MyISAM创建一个指定了DATA DIRECTORYINDEX DIRECTORY选项的表,并且找到现有.MYD.MYI文件,MyISAM总是返回错误,不会覆盖指定目录中的文件。

    Important

    您不能使用包含MySQL数据目录的路径名来指定DATA DIRECTORYINDEX DIRECTORY。包括分区表和单个表分区。(见Bug #32167。)

  • DELAY_KEY_WRITE

    如果您想延迟表的键更新直到关闭表,设置为 1。见delay_key_write系统变量在第7.1.8节,“服务器系统变量”的描述。(MyISAM 只有。)

  • ENCRYPTION

    ENCRYPTION子句启用或禁用InnoDB表的页面级数据加密。必须安装和配置密钥ring插件才能启用加密。可以在创建文件表空间中的表或在创建一般表空间中的表时指定ENCRYPTION子句。

    如果不指定ENCRYPTION子句,表将继承默认的架构加密。如果启用了table_encryption_privilege_check变量,创建一个加密设置与默认架构加密不同的表需要TABLE_ENCRYPTION_ADMIN特权。创建一般表空间中的表时,表和表空间加密必须一致。

    使用不支持加密的存储引擎时,不允许指定ENCRYPTION子句且值不是'N'或''。

    更多信息,请参见第17.13节,“InnoDB 数据静态加密”

  • ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 选项用于指定主和副存储引擎的表属性。这些选项保留供将来使用。

    分配给这两个选项的值必须是一个有效的JSON文档字符串或空字符串 (''),无效的JSON将被拒绝。

    CREATE TABLE t1 (c1 INT) ENGINE_ATTRIBUTE='{"key":"value"}';

    ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值可以重复使用,不会出现错误。在这种情况下,最后指定的值将被使用。

    ENGINE_ATTRIBUTESECONDARY_ENGINE_ATTRIBUTE 值不由服务器检查,也不会在更改表存储引擎时清除。

  • INSERT_METHOD

    如果您想将数据插入到 MERGE 表,您必须指定要插入的表。INSERT_METHOD 只有在 MERGE 表中有效,使用 FIRSTLAST 可以将插入数据发送到第一个或最后一个表,或者使用 NO 来防止插入。请参见第18.7节,“MERGE 存储引擎”

  • KEY_BLOCK_SIZE

    对于MyISAM表,KEY_BLOCK_SIZE可选地指定索引键块的大小(以字节为单位)。该值被视为提示;如果必要,可以使用不同的大小。单个索引定义中的KEY_BLOCK_SIZE值将覆盖表级别的KEY_BLOCK_SIZE值。

    对于InnoDB表,KEY_BLOCK_SIZE指定使用的大小(以千字节为单位),用于压缩的压缩InnoDB表。该值被视为提示;如果必要,InnoDB也可以使用不同的大小。KEY_BLOCK_SIZE只能小于或等于innodb_page_size值。值为0表示默认压缩页大小,等于innodb_page_size值的一半。取决于innodb_page_size,可能的KEY_BLOCK_SIZE值包括0、1、2、4、8和16。请参阅第17.9.1节,“InnoDB表压缩”获取更多信息。

    Oracle 建议在指定 InnoDB 表时启用innodb_strict_mode,当innodb_strict_mode 启用时,指定无效的 KEY_BLOCK_SIZE 值将返回错误;当innodb_strict_mode 禁用时,指定无效的 KEY_BLOCK_SIZE 值将返回警告,并忽略该选项。

    SHOW TABLE STATUSSHOW CREATE TABLE 中的 Create_options 列报告了实际使用的 KEY_BLOCK_SIZE

    InnoDB 只支持表级别的 KEY_BLOCK_SIZE

    KEY_BLOCK_SIZE 不支持 32KB 和 64KB 的innodb_page_size 值。InnoDB 表压缩不支持这些页面大小。

    InnoDB 在创建临时表时不支持 KEY_BLOCK_SIZE 选项。

  • MAX_ROWS

    您计划存储的表中的最大行数。这不是硬限制,而是对存储引擎的一个提示,表必须能够存储至少这个数量的行。

    Important

    MAX_ROWSNDB 表用于控制表分区的数量已经弃用。虽然在后续版本中仍然支持,但将来可能会被删除。请使用 PARTITION_BALANCE alternatively;见设置 NDB_TABLE 选项

    NDB 存储引擎将这个值当作最大值。如果您计划创建非常大的 NDB 集群表(包含数百万行),请使用这个选项来确保 NDB 分配足够的索引槽在哈希表中用于存储表的主键哈希,设置 MAX_ROWS = 2 * rows,其中 rows 是您计划插入到表中的行数。

    最大 MAX_ROWS 值为 4294967295;更大的值将被截断到这个限制。

  • MIN_ROWS

    MEMORY 存储引擎使用这个选项作为内存使用的提示。

  • PACK_KEYS

    只对 MyISAM 表格有效。将该选项设置为 1,如果想要拥有更小的索引。这通常使更新操作变慢,读取操作变快。将其设置为 0,禁用所有键的打包。将其设置为 DEFAULT,让存储引擎只对长的CHARVARCHARBINARYVARBINARY 列进行打包。

    如果不使用 PACK_KEYS,默认情况下只对字符串进行打包,不对数字进行打包。如果使用 PACK_KEYS=1,数字也会被打包。

    当packing二进制数键时,MySQL 使用前缀压缩:

    • 每个键都需要一个额外的字节来指示前一个键的字节数是下一个键的字节数。

    • 行指针在高字节优先顺序直接存储在键后面,以提高压缩效果。

    这意味着,如果你有许多相等的键在两个连续行上,那么所有后续的same键通常只占用两个字节(包括指向该行的指针)。与普通情况相比,后续键需要storage_size_for_key + pointer_size字节(其中指针大小通常为4)。反之,如果你有许多相同的数字,你才能从前缀压缩中获得明显的好处。如果所有键都是完全不同的,你每个键使用一个字节更多,且该键不能包含NULL值。在这种情况下,packed key length存储在标记该键是否为NULL的同一个字节中。

  • PASSWORD

    这个选项是无用的。

  • ROW_FORMAT

    定义了物理格式,用于存储行。

    在禁用严格模式的情况下,如果指定的行格式不支持,存储引擎将使用默认的行格式。表的实际行格式在SHOW TABLE STATUS中报告。Create_options列显示了CREATE TABLE语句中指定的行格式,同样SHOW CREATE TABLE也显示了该信息。

    存储引擎用于表的行格式选择不同。

    对于 InnoDB 表格:

    • 默认行格式由innodb_default_row_format定义,默认设置为DYNAMIC。当没有定义或使用ROW_FORMAT=DEFAULT时,使用默认行格式。

      如果没有定义ROW_FORMAT选项,或者使用ROW_FORMAT=DEFAULT,重建表格的操作也会悄然地将表格的行格式更改为由innodb_default_row_format定义的默认行格式。更多信息,请参见定义表格的行格式

    • 为了更高效地存储数据类型,特别是BLOB类型,使用DYNAMIC。见DYNAMIC 行格式关于DYNAMIC行格式的要求。

    • 要为InnoDB表启用压缩,指定ROW_FORMAT=COMPRESSED。不能在创建临时表时使用ROW_FORMAT=COMPRESSED选项。关于COMPRESSED行格式的要求,请参阅第17.9节,“InnoDB 表和页面压缩”

    • 可以通过指定REDUNDANT行格式来请求较早版本的MySQL所使用的行格式。

    • 如果您指定了非默认的ROW_FORMAT子句,考虑启用innodb_strict_mode配置选项。

    • ROW_FORMAT=FIXED不支持。如果在innodb_strict_mode禁用时指定ROW_FORMAT=FIXED,InnoDB会发出警告并假设ROW_FORMAT=DYNAMIC。如果在innodb_strict_mode启用时指定ROW_FORMAT=FIXED,InnoDB将返回错误。

    • 关于InnoDB行格式的更多信息,请参阅第17.10节,“InnoDB 行格式”

    对于 MyISAM 表,选项值可以是 FIXEDDYNAMIC,用于静态或变长行格式。myisampack 将类型设置为 COMPRESSED。请参阅第18.2.3节,“MyISAM 表存储格式”

    对于 NDB 表,缺省的 ROW_FORMATDYNAMIC

  • START TRANSACTION

    这是一个内部使用表选项,用于在支持原子 DDL 的存储引擎中,以单个、原子事务方式记录 CREATE TABLE ... SELECT 语句到二进制日志,当使用行级别复制时。只允许在 CREATE TABLE ... START TRANSACTION 后执行 BINLOGCOMMITROLLBACK 语句。关于相关信息,请参阅第15.1.1节,“原子数据定义语句支持”

  • STATS_AUTO_RECALC

    指定是否自动重新计算持久统计信息InnoDB表。值DEFAULT使得表的持久统计设置由innodb_stats_auto_recalc配置选项确定。值1在表中的10%数据发生变化时重新计算统计信息。值0防止对该表的自动重新计算;使用该设置,需要在对表进行大规模更改后执行ANALYZE TABLE语句以重新计算统计信息。关于持久统计信息的更多信息,请参见第17.8.10.1节,“配置持久优化器统计参数”

  • STATS_PERSISTENT

    指定是否为 InnoDB 表启用持久统计信息。值DEFAULT 使得表的持久统计信息设置由innodb_stats_persistent 配置选项确定。值1 启用表的持久统计信息,而值0 关闭该特性。在通过 CREATE TABLEALTER TABLE 语句启用持久统计信息后,使用ANALYZE TABLE 语句来计算统计信息,数据表加载代表性数据。关于持久统计信息的更多信息,请见第17.8.10.1节,“配置持久优化器统计参数”

  • STATS_SAMPLE_PAGES

    估算索引列的基数和其他统计信息时,采样索引页的数量,例如由ANALYZE TABLE 计算的。更多信息,请见第17.8.10.1节,“配置持久优化器统计参数”

  • TABLESPACE

    可以使用TABLESPACE子句在现有通用表空间、文件表空间或系统表空间中创建一个InnoDB表。

    CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name

    您指定的通用表空间必须在使用TABLESPACE子句之前存在。关于通用表空间的信息,请参阅第17.6.3.3节,“通用表空间”

    tablespace_name是一个区分大小写的标识符。它可以被引号或未引号。前向斜杠字符(/)不允许。以innodb_开头的名称保留用于特殊用途。

    要在系统表空间中创建一个表,请将tablespace名称指定为innodb_system

    CREATE TABLE tbl_name ... TABLESPACE [=] innodb_system

    TABLESPACE [=] innodb_system,您可以无论innodb_file_per_table设置,将一个未压缩行格式的表添加到系统表空间中,例如使用TABLESPACE [=] innodb_system添加一个具有ROW_FORMAT=DYNAMIC的表。

    要在文件表空间中创建一个表,请将tablespace名称指定为innodb_file_per_table

    CREATE TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table
    Note

    如果启用了innodb_file_per_table,创建一个InnoDB文件表空间时,不需要指定TABLESPACE=innodb_file_per_table。默认情况下,当innodb_file_per_table启用时,InnoDB表将被创建在文件表空间中。

    使用CREATE TABLE ... TABLESPACE=innodb_file_per_table时,DATA DIRECTORY子句是允许的,但在与CREATE TABLE子句组合使用时不支持。指定在DATA DIRECTORY子句中的目录必须是InnoDB所知的。更多信息,请参见.

    Note

    CREATE TEMPORARY TABLE语句中的TABLESPACE = innodb_file_per_tableTABLESPACE = innodb_temporary子句的支持已经废弃,预计将在 MySQL 的未来版本中删除。

    使用NDB表时,STORAGE选项只用于确定存储类型,可以是DISKMEMORY.

    TABLESPACE ... STORAGE DISK 将表分配到 NDB 集群磁盘数据表空间。STORAGE DISKCREATE TABLE 中不能单独使用,必须在 TABLESPACE tablespace_name 之前。

    对于 STORAGE MEMORY,表空间名称是可选的,因此可以使用 TABLESPACE tablespace_name STORAGE MEMORY 或直接使用 STORAGE MEMORY 来明确指定该表在内存中。

    请参阅第25.6.11节,“NDB 集群磁盘数据表”,了解更多信息。

  • UNION

    用于将多个相同的 MyISAM 表作为一个访问。只适用于 MERGE 表。请参阅第18.7节,“MERGE 存储引擎”

    您必须拥有对映射到 MERGE 表的表的SELECTUPDATEDELETE 权限。

    Note

    以前,所有表都必须在 MERGE 表本身的同一个数据库中。这一限制不再适用。

Table 分区

分区选项 可以控制使用 CREATE TABLE 创建的表的分区。

不所有在本节开头的分区选项 语法中显示的选项都可用于所有分区类型。请查看以下个别类型的列表,了解每种类型的信息,并查看第26章,分区,了解 MySQL 的更多关于分区的信息,以及 MySQL 分区的其他示例和语句。

可以修改、合并、添加或删除表中的分区。关于这些任务的基本信息,请查看 第15.1.9节,“ALTER TABLE 语句”。关于详细描述和示例,请查看第26.3节,“分区管理”

  • PARTITION BY

    如果使用,分区选项 子句以 PARTITION BY 开头。这子句包含确定分区的函数;该函数返回一个介于 1 到 num 之间的整数值,其中 num 是分区的数量。 (表中最多可以包含 1024 个用户定义的分区;后续讨论的子分区也包括在这个最大值内。)

    Note

    PARTITION BY 子句中使用的表达式 (expr) 不允许引用正在创建的表中的任何列;这种引用是明确不允许的,会导致语句失败(错误 #29444)。

  • HASH(expr)

    将一个或多个列哈希化以创建存储和定位行的键。expr 是使用一或多个表列的有效 MySQL 表达式(包括 MySQL 函数),产生单个整数值。例如,这些都是使用 PARTITION BY HASH 的有效CREATE TABLE 语句:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5))
        PARTITION BY HASH(col1);
    
    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
        PARTITION BY HASH ( YEAR(col3) );

    你不能使用 VALUES LESS THANVALUES IN 子句与 PARTITION BY HASH

    PARTITION BY HASH 使用 expr 的余数,除以分区的数量(即模)。例如和更多信息,请见第26.2.4节,“HASH 分区”

    LINEAR 关键字涉及到不同的算法。在这种情况下,行存储的分区号是通过一个或多个逻辑AND 操作计算的。关于线性哈希的讨论和示例,请见第26.2.4.1节,“LINEAR HASH 分区”

  • KEY(列名列表)

    这与HASH相似,except MySQL 提供哈希函数以确保数据的均匀分布。该列名列表参数只是一个包含 1 或更多表列的列表(最大:16)。这个示例展示了一个简单的按键分区表,具有 4 个分区:

    CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
        PARTITION BY KEY(col3)
        PARTITIONS 4;

    对于按键分区的表,您可以使用LINEAR关键字。它与按HASH分区相同,即使用&操作符,而不是模运算符(见第 26.2.4.1 节,“LINEAR HASH 分区”,和第 26.2.5 节,“KEY 分区”,了解详细信息)。这个示例使用按键分区来分布数据到 5 个分区:

    CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
        PARTITION BY LINEAR KEY(col3)
        PARTITIONS 5;

    支持[SUB]PARTITION BY [LINEAR] KEYALGORITHM={1 | 2}选项。ALGORITHM=1使服务器使用MySQL 5.1中的同一键哈希函数;ALGORITHM=2表示服务器使用默认的键哈希函数,用于MySQL 5.5 及更高版本的新建KEY分区表;(使用MySQL 5.5 及更高版本创建的KEY分区表不能在 MySQL 5.1 服务器上使用)。不指定该选项等同于使用ALGORITHM=2。这个选项主要用于升级或降级[LINEAR] KEY分区表,或者在MySQL 5.5 及更高版本服务器上创建可以在 MySQL 5.1 服务器上使用的KEYLINEAR KEY 分区表。更多信息,请参见第15.1.9.1节,“ALTER TABLE 分区操作”.

    mysqldump 将该选项嵌入版本注释中。

    ALGORITHM=1SHOW CREATE TABLE 的输出中显示,使用版本化注释方式与mysqldump 一致。ALGORITHM=2 始终从 SHOW CREATE TABLE 输出中省略,即使在创建原始表时指定了该选项。

    您不能同时使用VALUES LESS THANVALUES IN子句与PARTITION BY KEY

  • RANGE(expr)

    在这种情况下,expr 使用一组VALUES LESS THAN操作符显示值范围。使用范围分区时,您必须至少定义一个使用VALUES LESS THAN的分区。您不能使用VALUES IN与范围分区。

    Note

    对于以RANGE分区的表,VALUES LESS THAN必须与整数字面值或评估为单个整数值的表达式结合。在 MySQL 8.4 中,您可以在使用 PARTITION BY RANGE COLUMNS 定义的表中超越这个限制,后续部分将对其进行描述。

    假设您有一个要根据年份值分区的表,按照以下方案。

    Partition Number: Years Range:
    1990 及以前
    1 1991 到 1994
    2 1995 到 1998
    3 1999 到 2002
    4 2003 到 2005
    5 2006 及以后的版本

    实现这样一个分区方案的表可以使用以下语句:

    CREATE TABLE t1 (
        year_col  INT,
        some_data INT
    )
    PARTITION BY RANGE (year_col) (
        PARTITION p0 VALUES LESS THAN (1991),
        PARTITION p1 VALUES LESS THAN (1995),
        PARTITION p2 VALUES LESS THAN (1999),
        PARTITION p3 VALUES LESS THAN (2002),
        PARTITION p4 VALUES LESS THAN (2006),
        PARTITION p5 VALUES LESS THAN MAXVALUE
    );

    PARTITION ... VALUES LESS THAN ... 语句按顺序工作。VALUES LESS THAN MAXVALUE 可以指定否则指定的最大值以上的“剩余”值。

    VALUES LESS THAN 子句按顺序工作,类似于switch ... case语句块中的case部分(如C、Java、PHP等编程语言中),即每个子句的上限必须大于前一个,最后一个是引用MAXVALUE的。

  • RANGE COLUMNS(column_list)

    RANGE的变体,用于多列范围查询(即具有多个列的条件,如WHERE a = 1 AND b < 10WHERE a = 1 AND b = 10 AND c < 10)启用了对多个列的值范围指定,使用COLUMNS子句中的列名列表和每个PARTITION ... VALUES LESS THAN (value_list)分区定义子句中的列值集。 (在最简单的情况下,这个集只包含一个列。) 可以引用column_listvalue_list中的最大列数为16。

    COLUMNS子句中使用的column_list只能包含列名;每个列名列表中的列必须是以下MySQL数据类型之一:整数类型、字符串类型、时间或日期类型。不能使用BLOBTEXTSETENUMBIT或空间数据类型的列;也不能使用浮点数类型的列;在COLUMNS子句中也不能使用函数或算术表达式。

    在分区定义中使用的VALUES LESS THAN子句必须为每个列指定一个字面值;即,用于每个VALUES LESS THAN子句的值列表必须包含与在COLUMNS子句中列出的列数相同的值。使用更多或更少值在VALUES LESS THAN子句中将导致语句失败,错误信息为分区列表不一致...。不能使用NULLVALUES LESS THAN中出现的任何值。可以多次使用MAXVALUE,除非是第一个列,如下所示:

    CREATE TABLE rc (
        a INT NOT NULL,
        b INT NOT NULL
    )
    PARTITION BY RANGE COLUMNS(a,b) (
        PARTITION p0 VALUES LESS THAN (10,5),
        PARTITION p1 VALUES LESS THAN (20,10),
        PARTITION p2 VALUES LESS THAN (50,MAXVALUE),
        PARTITION p3 VALUES LESS THAN (65,MAXVALUE),
        PARTITION p4 VALUES LESS THAN (MAXVALUE,MAXVALUE)
    );

    每个用于VALUES LESS THAN值列表中的值必须与对应列的类型完全匹配,不进行转换。例如,您不能使用字符串'1'来匹配整数类型的列(必须使用数字1),也不能使用数字1来匹配字符串类型的列(在这种情况下,必须使用引号字符串:'1')。

    更多信息,请参见第26.2.1节,“范围分区”,和第26.4节,“分区剪枝”

  • LIST(expr)

    在分配表时,使用该方法非常有用,例如根据表的某一列的受限值集来分配,如州或国家代码。在这种情况下,可以将某个州或国家的所有行分配到一个分区中,也可以为某些州或国家保留一个分区。它类似于RANGE,但是只能使用VALUES IN来指定每个分区的可允许值。

    VALUES IN与一个要匹配的值列表一起使用。例如,您可以创建以下分区方案:

    CREATE TABLE client_firms (
        id   INT,
        name VARCHAR(35)
    )
    PARTITION BY LIST (id) (
        PARTITION r0 VALUES IN (1, 5, 9, 13, 17, 21),
        PARTITION r1 VALUES IN (2, 6, 10, 14, 18, 22),
        PARTITION r2 VALUES IN (3, 7, 11, 15, 19, 23),
        PARTITION r3 VALUES IN (4, 8, 12, 16, 20, 24)
    );

    在使用LIST分区时,必须至少定义一个分区使用VALUES IN。不能使用VALUES LESS THANPARTITION BY LIST

    Note

    对于以LIST分区的表,使用VALUES IN时,值列表必须只包含整数值。从MySQL 8.4开始,您可以使用LIST COLUMNS来克服这个限制,这个限制在本节后面描述。

  • LIST COLUMNS(column_list)

    LIST变体使查询使用多个列的比较条件进行分区裁剪(即具有条件如WHERE a = 5 AND b = 5WHERE a = 1 AND b = 10 AND c = 5)。它使您可以在COLUMNS子句中指定多个列,并在每个PARTITION ... VALUES IN (value_list)分区定义子句中指定每个值列表。

    关于列列表在LIST COLUMNS(column_list)和值列表在VALUES IN(value_list)的规则相同,除非在VALUES IN子句中不允许使用MAXVALUE,可以使用NULL

    当使用PARTITION BY LIST COLUMNS时,与使用PARTITION BY LIST的值列表不同。用于PARTITION BY LIST COLUMNS时,每个元素都必须是set列值;每个集中的值数量必须与COLUMNS子句中使用的列相同,且这些值的数据类型必须与列相同(顺序也相同)。在最简单的情况下,这个集只包含一个列。可以在column_listvalue_list中使用的列最大数量为16。

    以下CREATE TABLE语句定义了一个使用LIST COLUMNS分区表的示例:

    CREATE TABLE lc (
        a INT NULL,
        b INT NULL
    )
    PARTITION BY LIST COLUMNS(a,b) (
        PARTITION p0 VALUES IN( (0,0), (NULL,NULL) ),
        PARTITION p1 VALUES IN( (0,1), (0,2), (0,3), (1,1), (1,2) ),
        PARTITION p2 VALUES IN( (1,0), (2,0), (2,1), (3,0), (3,1) ),
        PARTITION p3 VALUES IN( (1,3), (2,2), (2,3), (3,2), (3,3) )
    );
  • PARTITIONS <em class="replaceable"><code>num</code></em>

    可以使用PARTITIONS num子句指定分区数量,where num是分区数量。如果同时使用该子句和PARTITION子句,num必须等于使用PARTITION子句声明的所有分区总数。

    Note

    无论是否使用PARTITIONS子句在创建以RANGELIST方式分区的表,您仍然需要在表定义中包含至少一个PARTITION VALUES子句(见下文)。

  • SUBPARTITION BY

    可以将分区进一步分为多个子分区。可以使用可选的SUBPARTITION BY子句来表示。子分区可以通过HASHKEY进行,且可以是LINEAR。这些与之前描述的等价分区类型相同。(不可能以LISTRANGE方式子分区。)

    SUBPARTITIONS关键字后跟一个整数值来指定子分区数量。

  • PARTITIONSSUBPARTITIONS子句的值进行严格检查,且该值必须遵守以下规则:

    • 该值必须是正整数。

    • 不允许前导零。

    • 该值必须是整数字面量,不能是表达式。例如,PARTITIONS 0.2E+01 不允许,即使 0.2E+01 evaluate 到 2。 (Bug #15890)

  • partition_definition

    每个分区可以单独使用一个partition_definition子句。该子句的组成部分如下:

    • PARTITION partition_name

      指定分区的逻辑名称。

    • VALUES

      对于范围分区,每个分区都必须包含一个VALUES LESS THAN子句;对于列表分区,您必须为每个分区指定一个VALUES IN子句,以确定要存储在该分区的行。见第26章,分区,了解分区类型的语法示例。

    • [STORAGE] ENGINE

      MySQL 对于 PARTITIONSUBPARTITION 都接受一个[STORAGE] ENGINE 选项。当前,唯一可以使用该选项的方式是将所有分区或所有子分区设置为同一个存储引擎,并尝试在同一张表中为分区或子分区设置不同的存储引擎会raise错误ERROR 1469 (HY000): 在 MySQL 的这个版本中,分区的混杂handler不允许

    • COMMENT

      可以使用可选的COMMENT子句来指定分区的字符串描述。示例:

      COMMENT = 'Data for the years previous to 1999'

      分区注释的最大长度为1024个字符。

    • DATA DIRECTORYINDEX DIRECTORY

      DATA DIRECTORYINDEX DIRECTORY 可以用来指示该分区的数据和索引存储目录。同时,data_dirindex_dir 都必须是绝对系统路径名。

      指定在DATA DIRECTORY子句中的目录必须被InnoDB所知。更多信息,请参见使用 DATA DIRECTORY 子句

      要使用DATA DIRECTORYINDEX DIRECTORY 分区选项,必须拥有FILE特权。

      示例:

      CREATE TABLE th (id INT, name VARCHAR(30), adate DATE)
      PARTITION BY LIST(YEAR(adate))
      (
        PARTITION p1999 VALUES IN (1995, 1999, 2003)
          DATA DIRECTORY = '/var/appdata/95/data'
          INDEX DIRECTORY = '/var/appdata/95/idx',
        PARTITION p2000 VALUES IN (1996, 2000, 2004)
          DATA DIRECTORY = '/var/appdata/96/data'
          INDEX DIRECTORY = '/var/appdata/96/idx',
        PARTITION p2001 VALUES IN (1997, 2001, 2005)
          DATA DIRECTORY = '/var/appdata/97/data'
          INDEX DIRECTORY = '/var/appdata/97/idx',
        PARTITION p2002 VALUES IN (1998, 2002, 2006)
          DATA DIRECTORY = '/var/appdata/98/data'
          INDEX DIRECTORY = '/var/appdata/98/idx'
      );

      DATA DIRECTORYINDEX DIRECTORYCREATE TABLE 语句的table_option 子句中行为与用于 MyISAM 表的相同。

      每个分区最多只能指定一个数据目录和一个索引目录。如果不指定,数据和索引默认存储在表的数据库目录下。

      如果启用了NO_DIR_IN_CREATE,则忽略DATA DIRECTORYINDEX DIRECTORY选项创建分区表。

    • MAX_ROWSMIN_ROWS

      可以分别指定要存储在分区中的最大和最小行数。对max_number_of_rowsmin_number_of_rows的值必须是正整数。与同名的表级选项一样,这些选项只作为服务器的“建议”,不是硬限制。

    • TABLESPACE

      可以用来指定一个InnoDB文件每个表空间为分区,通过指定TABLESPACE `innodb_file_per_table`。所有分区都必须属于同一个存储引擎。

      InnoDB表分区置于共享的InnoDB表空间中不支持。共享表空间包括InnoDB系统表空间和一般表空间。

  • subpartition_definition

    分区定义可选地包含一个或多个subpartition_definition子句。每个这些子句至少包含SUBPARTITION name,其中name是子分区的标识符。除了将PARTITION关键字替换为SUBPARTITION外,子分区定义语法与分区定义语法相同。

    必须使用HASHKEYRANGELIST分区进行子分区。见第26.2.6节,“子分区”

使用生成列进行分区

使用生成列进行分区是允许的。例如:

CREATE TABLE t1 (
  s1 INT,
  s2 INT AS (EXP(s1)) STORED
)
PARTITION BY LIST (s2) (
  PARTITION p1 VALUES IN (1)
);

分区视图一个生成列为普通列,这使得可以绕过一些不允许在分区中的函数限制(见第26.6.3节,“与函数相关的分区限制”)。前面的示例演示了这个技术:EXP()不能直接在PARTITION BY子句中使用,但使用EXP()定义的生成列是允许的。