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 允许最多 40 亿个表。
有关表的物理表示形式的信息,请参阅 第 15.1.20.1 节,“由 CREATE TABLE 创建的文件”。
关于 CREATE TABLE 语句,本节将通过以下主题进行描述:
表名
tbl_name表名可以指定为
db_name.tbl_name来在特定数据库中创建表。这无论是否存在默认数据库都适用,前提是数据库存在。如果使用带引号的标识符,请分别对数据库和表名加引号。例如,写成`mydb`.`mytbl`,而不是`mydb.mytbl`。关于允许的表名的规则,请参见 第 11.2 节,“模式对象名称”。
IF NOT EXISTS防止在表存在时发生错误。但是,不会验证现有表是否具有与
CREATE TABLE语句中指示的结构相同的结构。
临时表
在创建表时,可以使用 TEMPORARY 关键字。TEMPORARY 表仅在当前会话中可见,并在会话关闭时自动删除。有关更多信息,请参见 第 15.1.20.2 节,“CREATE TEMPORARY TABLE 语句”。
表克隆和复制
LIKE使用
CREATE TABLE ... LIKE根据另一个表的定义创建空表,包括原始表中定义的任何列属性和索引。CREATE TABLE new_tbl LIKE orig_tbl;有关更多信息,请参见 第 15.1.20.3 节,“CREATE TABLE ... LIKE 语句”。
[AS]query_expression要从另一个表创建表,请在
CREATE TABLE语句末尾添加一个SELECT语句。CREATE TABLE new_tbl AS SELECT * FROM orig_tbl;有关更多信息,请参见 第 15.1.20.4 节,“CREATE TABLE ... SELECT 语句”。
IGNORE | REPLACEIGNORE和REPLACE选项指示在使用SELECT语句复制表时如何处理重复唯一键值的行。有关更多信息,请参见 第 15.1.20.4 节,“CREATE TABLE ... SELECT 语句”。
列数据类型和属性
每个表最多有 4096 列,但对于给定表,实际最大值可能更小,这取决于 第 10.4.7 节,“表列数和行大小限制” 中讨论的因素。
data_typedata_type表示列定义中的数据类型。有关指定列数据类型可用的语法的完整描述以及有关每种类型属性的信息,请参见 第 13 章,数据类型。AUTO_INCREMENT仅适用于整数类型。字符数据类型(
CHAR、VARCHAR、TEXT类型、ENUM、SET以及任何同义词)可以包含CHARACTER SET来指定列的字符集。CHARSET是CHARACTER SET的同义词。可以使用COLLATE属性为字符集指定排序规则,以及任何其他属性。有关详细信息,请参见 第 12 章,字符集、排序规则、Unicode。示例CREATE TABLE t (c CHAR(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin);对于
CHAR、VARCHAR、BINARY和VARBINARY列,可以使用语法指定索引前缀长度,创建仅使用列值的前导部分的索引。col_name(length)BLOB和TEXT列也可以被索引,但必须提供前缀长度。前缀长度以字符为单位表示非二进制字符串类型,以字节为单位表示二进制字符串类型。也就是说,索引条目包含每个列值的前length个字符(对于CHAR、VARCHAR和TEXT列),或每个列值的前length个字节(对于BINARY、VARBINARY和BLOB列)。像这样只索引列值的前缀可以使索引文件更小。有关索引前缀的更多信息,请参见 第 15.1.15 节,“CREATE INDEX 语句”。只有
InnoDB和MyISAM存储引擎支持对BLOB和TEXT列进行索引。例如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 中,只有
InnoDB、MyISAM和MEMORY存储引擎支持对可以包含NULL值的列进行索引。在其他情况下,必须将索引列声明为NOT NULL,否则会导致错误。DEFAULT为列指定默认值。有关默认值处理的更多信息(包括列定义不包含显式
DEFAULT值的情况),请参见 第 13.6 节,“数据类型默认值”。如果启用了
NO_ZERO_DATE或NO_ZERO_IN_DATESQL 模式,并且根据该模式日期值默认值不正确,则如果未启用严格 SQL 模式,CREATE TABLE会生成警告,如果启用了严格模式,则会生成错误。例如,在启用了NO_ZERO_IN_DATE的情况下,c1 DATE DEFAULT '2010-00-00'会生成警告。VISIBLE、INVISIBLE指定列可见性。如果未出现任何关键字,则默认值为
VISIBLE。表必须至少包含一列可见列。尝试使所有列不可见会导致错误。有关更多信息,请参见 第 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_ZEROSQL 模式,则可以将0存储在AUTO_INCREMENT列中作为0,而不会生成新的序列值。请参见 第 7.1.11 节,“服务器 SQL 模式”。每个表只能包含一个
AUTO_INCREMENT列,它必须被索引,并且不能具有DEFAULT值。AUTO_INCREMENT列仅在它只包含正值时才能正常工作。插入负数被视为插入非常大的正数。这是为了避免数字从正数“环绕”到负数时的精度问题,并且还确保您不会意外地获得包含0的AUTO_INCREMENT列。对于
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 节,“服务器系统变量”。有关
InnoDB和AUTO_INCREMENT的信息,请参阅 第 17.6.1.6 节,“InnoDB 中的 AUTO_INCREMENT 处理”。有关AUTO_INCREMENT和 MySQL 复制的信息,请参阅 第 19.5.1.1 节,“复制和 AUTO_INCREMENT”。COMMENT可以使用
COMMENT选项为列指定注释,最多 1024 个字符。该注释将由SHOW CREATE TABLE和SHOW FULL COLUMNS语句显示。它也会在信息模式COLUMNS表的COLUMN_COMMENT列中显示。COLUMN_FORMAT在 NDB Cluster 中,还可以使用
COLUMN_FORMAT为NDB表的各个列指定数据存储格式。允许的列格式为FIXED、DYNAMIC和DEFAULT。FIXED用于指定固定宽度存储,DYNAMIC允许列为可变宽度,而DEFAULT使列使用由列数据类型确定的固定宽度或可变宽度存储(可能被ROW_FORMAT指定符覆盖)。对于
NDB表,COLUMN_FORMAT的默认值为FIXED。在 NDB Cluster 中,使用
COLUMN_FORMAT=FIXED定义的列的最大可能偏移量为 8188 字节。有关更多信息和可能的解决方法,请参阅 第 25.2.7.5 节,“与 NDB Cluster 中的数据库对象相关的限制”。COLUMN_FORMAT目前对使用除NDB之外的存储引擎的表的列没有任何影响。MySQL 8.4 会静默忽略COLUMN_FORMAT。ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE选项用于为主存储引擎和辅助存储引擎指定列属性。这些选项为将来使用保留。分配给此选项的值是一个包含有效 JSON 文档的字符串文字或空字符串('')。无效的 JSON 会被拒绝。
CREATE TABLE t1 (c1 INT ENGINE_ATTRIBUTE='{"key":"value"}');ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE值可以重复,不会出现错误。在这种情况下,将使用最后指定的 value。ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE值不会由服务器检查,也不会在更改表的存储引擎时被清除。STORAGE对于
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 Cluster 捆绑在一起的mysqld 版本中受支持;它在 MySQL 的任何其他版本中都不被识别,在这些版本中,任何尝试使用STORAGE关键字都会导致语法错误。GENERATED ALWAYS用于指定生成的列表达式。有关生成列 的信息,请参阅 第 15.1.20.8 节,“CREATE TABLE 和生成列”。
存储的生成列 可以被索引。
InnoDB支持对虚拟生成列 的辅助索引。请参阅 第 15.1.20.9 节,“辅助索引和生成列”。
索引、外键和 CHECK 约束
多个关键字适用于创建索引、外键和CHECK 约束。有关以下描述以外的一般背景信息,请参阅 第 15.1.15 节,“CREATE INDEX 语句”、第 15.1.20.5 节,“FOREIGN KEY 约束” 和 第 15.1.20.6 节,“CHECK 约束”。
CONSTRAINTsymbolCONSTRAINT子句可以用来命名约束。如果未给出该子句,或未在symbolCONSTRAINT关键字后包含symbol,MySQL 会自动生成约束名称,但以下情况除外。如果使用symbol值,它必须针对每个模式(数据库)、每个约束类型都是唯一的。重复的symbol会导致错误。另请参阅有关在 第 11.2.1 节,“标识符长度限制” 中生成的约束标识符的长度限制的讨论。注意如果在定义外键时未给出
CONSTRAINT子句,或未在symbolCONSTRAINT关键字后包含symbol,MySQL 会自动生成约束名称。SQL 标准规定所有类型的约束(主键、唯一索引、外键、检查)属于同一个命名空间。在 MySQL 中,每种约束类型在每个模式中都有自己的命名空间。因此,每种约束类型的名称必须在每个模式中都是唯一的,但不同类型的约束可以具有相同的名称。
PRIMARY KEY唯一索引,其中所有键列都必须定义为
NOT NULL。如果它们没有被显式声明为NOT NULL,MySQL 会隐式地(并静默地)声明它们。表只能有一个PRIMARY KEY。一个PRIMARY KEY的名称总是PRIMARY,因此不能用作任何其他类型索引的名称。如果你没有
PRIMARY KEY,而应用程序要求你在表中提供PRIMARY KEY,MySQL 会返回第一个没有NULL列的UNIQUE索引作为PRIMARY KEY。在
InnoDB表中,使PRIMARY KEY保持简短,以最大程度地减少辅助索引的存储开销。每个辅助索引条目都包含相应行的主键列的副本。(请参阅 第 17.6.2.1 节,“聚集索引和辅助索引”。)在创建的表中,
PRIMARY KEY放在第一位,后面是所有UNIQUE索引,然后是非唯一索引。这有助于 MySQL 优化器优先考虑使用哪个索引,以及更快地检测重复的UNIQUE键。PRIMARY KEY可以是多列索引。但是,你不能使用列规范中的PRIMARY KEY键属性来创建多列索引。这样做只会将该单个列标记为主键。你必须使用单独的PRIMARY KEY(子句。key_part, ...)如果表有一个
PRIMARY KEY或UNIQUE NOT NULL索引,它包含一个具有整数类型 的单列,则可以使用_rowid来引用SELECT语句中的索引列,如 唯一索引 中所述。在 MySQL 中,一个
PRIMARY KEY的名称是PRIMARY。对于其他索引,如果你没有分配名称,则索引将被分配与第一个索引列相同的名称,并带有一个可选的后缀 (_2、_3、...) 以使其唯一。可以使用SHOW INDEX FROM来查看表的索引名称。请参阅 第 15.7.7.23 节,“SHOW INDEX 语句”。tbl_nameKEY | INDEXKEY通常是INDEX的同义词。键属性PRIMARY KEY也可以在列定义中指定为KEY。为了与其他数据库系统兼容而实现了此功能。UNIQUEUNIQUE索引创建约束,使得索引中的所有值都必须是不同的。如果你尝试添加一个与现有行匹配的键值的新行,就会出现错误。对于所有引擎,一个UNIQUE索引允许对可以包含NULL的列使用多个NULL值。如果你为UNIQUE索引中的列指定一个前缀值,则列值在该前缀长度内必须是唯一的。如果表有一个
PRIMARY KEY或UNIQUE NOT NULL索引,它包含一个具有整数类型 的单列,则可以使用_rowid来引用SELECT语句中的索引列,如 唯一索引 中所述。FULLTEXT一个
FULLTEXT索引是一种用于全文本搜索的特殊类型的索引。只有InnoDB和MyISAM存储引擎支持FULLTEXT索引。它们只能从CHAR、VARCHAR和TEXT列创建。索引始终在整个列上进行;不支持列前缀索引,并且如果指定,则忽略任何前缀长度。有关操作的详细信息,请参阅 第 14.9 节,“全文本搜索函数”。如果全文本索引和搜索操作需要特殊处理,则可以将WITH PARSER子句指定为index_option值,以将解析器插件与索引关联起来。此子句仅对FULLTEXT索引有效。InnoDB和MyISAM支持全文本解析器插件。有关更多信息,请参阅 全文本解析器插件 和 编写全文本解析器插件。SPATIAL可以在空间数据类型上创建
SPATIAL索引。空间类型仅适用于InnoDB和MyISAM表,并且索引列必须声明为NOT NULL。请参阅 第 13.4 节,“空间数据类型”。FOREIGN KEYMySQL 支持外键,允许您跨表交叉引用相关数据,以及外键约束,有助于保持这些分散数据的 一致性。有关定义和选项的信息,请参阅
reference_definition和reference_option。使用
InnoDB存储引擎的分区表不支持外键。有关更多信息,请参阅 第 26.6 节,“分区限制和局限性”。CHECKCHECK子句允许创建约束以检查表行中的数据值。请参阅 第 15.1.20.6 节,“CHECK 约束”。key_partkey_part规范可以以ASC或DESC结尾,以指定索引值是按升序还是降序存储。如果未给出任何排序说明符,则默认为升序。前缀由
length属性定义,对于使用REDUNDANT或COMPACT行格式的InnoDB表,前缀长度限制为 767 字节。对于使用DYNAMIC或COMPRESSED行格式的InnoDB表,前缀长度限制为 3072 字节。对于MyISAM表,前缀长度限制为 1000 字节。前缀 限制 以字节为单位。但是,在
CREATE TABLE、ALTER TABLE和CREATE INDEX语句中用于索引规范的前缀 长度 被解释为非二进制字符串类型的字符数 (CHAR、VARCHAR、TEXT) 和二进制字符串类型的字节数 (BINARY、VARBINARY、BLOB)。为使用多字节字符集的非二进制字符串列指定前缀长度时,请牢记这一点。key_part规范的expr可以采用(CAST的形式,以在json_pathAStypeARRAY)JSON列上创建多值索引。多值索引 提供有关创建、使用以及多值索引限制和局限性的详细信息。
index_type某些存储引擎允许您在创建索引时指定索引类型。
index_type说明符的语法是USING。type_name示例
CREATE TABLE lookup (id INT, INDEX USING BTREE (id) ) ENGINE = MEMORY;USING的首选位置是在索引列列表之后。它可以在列列表之前给出,但是对该位置使用该选项的支持已过时,您应该预计它将在未来的 MySQL 版本中被删除。index_optionindex_option值指定索引的附加选项。KEY_BLOCK_SIZE对于
MyISAM表,KEY_BLOCK_SIZE可选地指定用于索引键块的大小(以字节为单位)。该值被视为提示;如果需要,可以使用不同的尺寸。为单个索引定义指定的KEY_BLOCK_SIZE值将覆盖表级KEY_BLOCK_SIZE值。有关表级
KEY_BLOCK_SIZE属性的信息,请参阅 表选项。WITH PARSERWITH PARSER选项只能与FULLTEXT索引一起使用。如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引关联。InnoDB和MyISAM支持全文解析器插件。如果您有一个MyISAM表,并与之关联了一个全文解析器插件,则可以使用ALTER TABLE将该表转换为InnoDB。COMMENT索引定义可以包括一个可选的注释,最多 1024 个字符。
可以使用
index_optionCOMMENT子句为单个索引设置InnoDBMERGE_THRESHOLD值。请参阅 第 17.8.11 节,“配置索引页的合并阈值”。VISIBLE、INVISIBLE指定索引可见性。索引默认可见。不可见索引不会被优化器使用。指定索引可见性适用于除主键(显式或隐式)以外的索引。有关更多信息,请参阅 第 10.3.12 节,“不可见索引”。
ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE选项用于指定主存储引擎和辅助存储引擎的索引属性。这些选项保留供将来使用。
有关允许的
index_option值的更多信息,请参阅 第 15.1.15 节,“CREATE INDEX 语句”。有关索引的更多信息,请参阅 第 10.3.1 节,“MySQL 如何使用索引”。有关
reference_definition语法细节和示例,请参阅 第 15.1.20.5 节,“FOREIGN KEY 约束”。InnoDB和NDB表支持检查外键约束。被引用表的列必须始终被明确命名。ON DELETE和ON UPDATE操作都支持外键。有关更详细的信息和示例,请参阅 第 15.1.20.5 节,“FOREIGN KEY 约束”。对于其他存储引擎,MySQL 服务器将在
CREATE TABLE语句中解析并忽略FOREIGN KEY语法。重要对于熟悉 ANSI/ISO SQL 标准的用户,请注意,没有存储引擎(包括
InnoDB)识别或强制执行在引用完整性约束定义中使用的MATCH子句。使用显式MATCH子句不会产生指定的效果,还会导致ON DELETE和ON UPDATE子句被忽略。由于这些原因,应避免指定MATCH。SQL 标准中的
MATCH子句控制复合(多列)外键中的NULL值在与主键进行比较时的处理方式。InnoDB本质上实现了MATCH SIMPLE定义的语义,允许外键全部或部分为NULL。在这种情况下,包含此类外键的(子表)行被允许插入,并且不匹配引用(父表)中的任何行。可以使用触发器来实现其他语义。此外,MySQL 要求被引用列被索引以提高性能。但是,
InnoDB不强制执行任何要求,即被引用列被声明为UNIQUE或NOT NULL。对于诸如UPDATE或DELETE CASCADE之类的操作,处理对非唯一键或包含NULL值的键的外键引用没有明确定义。建议您仅使用引用同时为UNIQUE(或PRIMARY)和NOT NULL的键的外键。MySQL 解析但忽略 “内联
REFERENCES规范”(如 SQL 标准中定义的那样),其中引用被定义为列规范的一部分。MySQL 仅在将REFERENCES子句指定为单独的FOREIGN KEY规范的一部分时才接受它。有关更多信息,请参阅 第 1.7.2.3 节,“FOREIGN KEY 约束差异”。有关
RESTRICT、CASCADE、SET NULL、NO ACTION和SET DEFAULT选项的信息,请参阅 第 15.1.20.5 节,“FOREIGN KEY 约束”。
表选项
表选项用于优化表的行为。在大多数情况下,您不必指定任何选项。这些选项适用于所有存储引擎,除非另有说明。不适用于给定存储引擎的选项可能会被接受并作为表定义的一部分记住。然后,如果稍后使用 ALTER TABLE 将表转换为使用其他存储引擎,则这些选项将适用。
ENGINE指定表的存储引擎,使用下表中显示的名称之一。引擎名称可以不加引号或加引号。加引号的名称
'DEFAULT'将被识别,但会被忽略。存储引擎 描述 InnoDB支持事务的表,具有行级锁定和外键。新表的默认存储引擎。请参阅 第 17 章,InnoDB 存储引擎,特别是 第 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 Cluster 8.4。默认情况下,如果指定的存储引擎不可用,则语句将失败并出现错误。可以通过从服务器 SQL 模式中删除
NO_ENGINE_SUBSTITUTION(参见 第 7.1.11 节,“服务器 SQL 模式”)来覆盖此行为,以便 MySQL 允许使用默认存储引擎替换指定的引擎。通常,在这种情况下,默认存储引擎是InnoDB,它是default_storage_engine系统变量的默认值。当禁用NO_ENGINE_SUBSTITUTION时,如果未遵守存储引擎规范,则会出现警告。AUTOEXTEND_SIZE定义
InnoDB在表空间已满时扩展表空间大小的量。该设置必须是 4MB 的倍数。默认设置是 0,这会导致表空间根据隐式默认行为进行扩展。有关更多信息,请参见 第 17.6.3.9 节,“表空间 AUTOEXTEND_SIZE 配置”。AUTO_INCREMENT表的初始
AUTO_INCREMENT值。在 MySQL 8.4 中,这适用于MyISAM、MEMORY、InnoDB和ARCHIVE表。要为不支持AUTO_INCREMENT表选项的引擎设置第一个自动递增值,请在创建表后插入一行 “虚拟” 行,其值比所需值小 1,然后删除虚拟行。对于在
CREATE TABLE语句中支持AUTO_INCREMENT表选项的引擎,也可以使用ALTER TABLE来重置tbl_nameAUTO_INCREMENT =NAUTO_INCREMENT值。该值不能低于该列中当前的最大值。AVG_ROW_LENGTH表平均行长度的近似值。您只需要为具有可变大小行的较大型表设置此值。
创建
MyISAM表时,MySQL 使用MAX_ROWS和AVG_ROW_LENGTH选项的乘积来决定生成的表的大小。如果您未指定任何选项,则MyISAM数据和索引文件的最大大小默认情况下为 256TB。(如果您的操作系统不支持那么大的文件,则表大小会受到文件大小限制。)如果您希望保持指针大小以使索引更小更快,并且您实际上不需要大文件,则可以通过设置myisam_data_pointer_size系统变量来减小默认指针大小。(参见 第 7.1.8 节,“服务器系统变量”。)如果您希望所有表都能增长到默认限制以上,并且愿意使表比必要时略微慢一些,并且更大一些,则可以通过设置此变量来增加默认指针大小。将该值设置为 7 允许表大小高达 65,536TB。[DEFAULT] CHARACTER SET指定表的默认字符集。
CHARSET是CHARACTER SET的同义词。如果字符集名称为DEFAULT,则使用数据库字符集。CHECKSUM如果您希望 MySQL 为所有行维护一个实时校验和(即 MySQL 在表更改时自动更新的校验和),请将其设置为 1。这使表更新速度略慢,但也使查找损坏的表更容易。
CHECKSUM TABLE语句报告校验和。(仅MyISAM。)[DEFAULT] COLLATE指定表的默认排序规则。
COMMENT表的注释,最多 2048 个字符。
您可以使用
table_optionCOMMENT子句为表设置InnoDBMERGE_THRESHOLD值。参见 第 17.8.11 节,“配置索引页的合并阈值”。设置 NDB_TABLE 选项。 在创建
NDB表的CREATE TABLE或更改表的ALTER TABLE语句中,表的注释也可以用于指定四个NDB_TABLE选项中的一个到四个,即NOLOGGING、READ_BACKUP、PARTITION_BALANCE或FULLY_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 Information SchemaTABLES表的 TABLE_COMMENT 列提供。此注释语法也支持
NDB表的ALTER TABLE语句。请记住,与ALTER TABLE一起使用的表注释将替换该表可能之前拥有的任何现有注释。在表注释中设置
MERGE_THRESHOLD选项对于NDB表不受支持(它将被忽略)。有关完整的语法信息和示例,请参见 第 15.1.20.12 节,“设置 NDB 注释选项”。
COMPRESSION用于
InnoDB表页面级压缩的压缩算法。支持的值包括Zlib、LZ4和None。COMPRESSION属性是在引入透明页面压缩功能时引入的。页面压缩仅支持位于 每个表一个文件 表空间中的InnoDB表,并且仅在支持稀疏文件和空洞穿孔的 Linux 和 Windows 平台上可用。有关更多信息,请参见 第 17.9.2 节,“InnoDB 页面压缩”。CONNECTIONFEDERATED表的连接字符串。注意旧版本的 MySQL 使用
COMMENT选项表示连接字符串。DATA DIRECTORY、INDEX DIRECTORY对于
InnoDB,DATA DIRECTORY='子句允许在数据目录之外创建表。必须启用directory'innodb_file_per_table变量才能使用DATA DIRECTORY子句。必须指定完整的目录路径,并且InnoDB必须知道该路径。有关更多信息,请参见 第 17.6.1.2 节,“在外部创建表”。创建
MyISAM表时,可以使用DATA DIRECTORY='子句、directory'INDEX DIRECTORY='子句或两者。它们分别指定将directory'MyISAM表的数据文件和索引文件放在哪里。与InnoDB表不同,MySQL 在创建具有DATA DIRECTORY或INDEX DIRECTORY选项的MyISAM表时不会创建对应于数据库名称的子目录。文件将创建在指定的目录中。您必须拥有
FILE权限才能使用DATA DIRECTORY或INDEX DIRECTORY表选项。重要表级
DATA DIRECTORY和INDEX DIRECTORY选项对于分区表将被忽略。(错误 #32091)这些选项仅在您没有使用
--skip-symbolic-links选项时有效。您的操作系统也必须具有一个正常工作的线程安全的realpath()调用。参见 第 10.12.2.2 节,“在 Unix 上使用符号链接到 MyISAM 表”,以获取更完整的信息。如果
MyISAM表在没有DATA DIRECTORY选项的情况下创建,则.MYD文件将在数据库目录中创建。默认情况下,如果MyISAM在这种情况下找到了现有.MYD文件,它将覆盖该文件。对于在没有INDEX DIRECTORY选项的情况下创建的表,.MYI文件也是如此。要禁止此行为,请使用--keep_files_on_create选项启动服务器,在这种情况下,MyISAM不会覆盖现有文件,而是返回错误。如果
MyISAM表在使用DATA DIRECTORY或INDEX DIRECTORY选项的情况下创建,并且找到了现有的.MYD或.MYI文件,则MyISAM将始终返回错误,并且不会覆盖指定目录中的文件。重要您不能使用包含 MySQL 数据目录的路径名称与
DATA DIRECTORY或INDEX DIRECTORY一起使用。这包括分区表和单个表分区。(参见错误 #32167。)DELAY_KEY_WRITE如果您希望延迟对表的键更新,直到关闭表为止,请将其设置为 1。参见
delay_key_write系统变量在 第 7.1.8 节,“服务器系统变量” 中的描述。(仅MyISAM。)ENCRYPTIONENCRYPTION子句启用或禁用InnoDB表的页面级数据加密。必须安装和配置密钥环插件才能启用加密。可以在每个表一个文件表空间中创建表时或在通用表空间中创建表时指定ENCRYPTION子句。如果未指定
ENCRYPTION子句,则表将继承默认的架构加密。如果启用了table_encryption_privilege_check变量,则需要TABLE_ENCRYPTION_ADMIN权限才能创建与默认架构加密不同的ENCRYPTION子句设置的表。在通用表空间中创建表时,表和表空间加密必须匹配。当使用不支持加密的存储引擎时,不允许指定
ENCRYPTION子句,其值为除'N'或''以外的值。有关更多信息,请参见第 17.13 节,“InnoDB 数据休眠加密”。
ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE选项用于为主要和辅助存储引擎指定表属性。这些选项为将来使用保留。分配给这些选项的任何一个的值必须是包含有效 JSON 文档的字符串文字或空字符串 (''). 无效 JSON 会被拒绝。
CREATE TABLE t1 (c1 INT) ENGINE_ATTRIBUTE='{"key":"value"}';ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE值可以重复,不会出现错误。在这种情况下,将使用最后指定的 value。ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE值不会由服务器检查,也不会在更改表的存储引擎时被清除。INSERT_METHOD如果要将数据插入
MERGE表,必须使用INSERT_METHOD指定应将行插入的表。INSERT_METHOD是仅对MERGE表有用的选项。使用FIRST或LAST值将插入操作转到第一个或最后一个表,或者使用NO值来阻止插入。请参见第 18.7 节,“MERGE 存储引擎”。KEY_BLOCK_SIZE对于
MyISAM表,KEY_BLOCK_SIZE可选地指定用于索引键块的大小(以字节为单位)。该值被视为提示;如果需要,可以使用不同的尺寸。为单个索引定义指定的KEY_BLOCK_SIZE值将覆盖表级KEY_BLOCK_SIZE值。对于
InnoDB表,KEY_BLOCK_SIZE指定用于压缩InnoDB表的页面大小(以 KB 为单位)。KEY_BLOCK_SIZE值被视为提示;如果需要,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表指定KEY_BLOCK_SIZE时启用innodb_strict_mode。启用innodb_strict_mode时,指定无效的KEY_BLOCK_SIZE值将返回错误。如果innodb_strict_mode被禁用,无效的KEY_BLOCK_SIZE值将导致警告,并且KEY_BLOCK_SIZE选项将被忽略。对
SHOW TABLE STATUS的响应中的Create_options列报告表实际使用的KEY_BLOCK_SIZE,SHOW CREATE TABLE也是如此。InnoDB仅在表级别支持KEY_BLOCK_SIZE。对于 32 KB 和 64 KB
innodb_page_size值,不支持KEY_BLOCK_SIZE。InnoDB表压缩不支持这些页面大小。创建临时表时,
InnoDB不支持KEY_BLOCK_SIZE选项。MAX_ROWS计划在表中存储的最大行数。这不是硬性限制,而是对存储引擎的提示,表示该表必须能够存储至少这么多行。
重要使用
MAX_ROWS和NDB表来控制表分区数量已弃用。它在更高版本中为了向后兼容而继续受支持,但在将来版本中可能会被删除。请改用 PARTITION_BALANCE;请参见设置 NDB_TABLE 选项。NDB存储引擎将此值视为最大值。如果计划创建非常大的 NDB Cluster 表(包含数百万行),应使用此选项以确保NDB在用于存储表主键哈希值的哈希表中分配足够的索引插槽数量,方法是设置MAX_ROWS = 2 *,其中rowsrows是预期插入表的行数。最大
MAX_ROWS值为 4294967295;大于此限制的值将被截断为该限制。MIN_ROWS计划在表中存储的最小行数。
MEMORY存储引擎将此选项用作有关内存使用的提示。PACK_KEYS仅对
MyISAM表有效。如果希望拥有更小的索引,请将此选项设置为 1。这通常会使更新变慢,而读取速度更快。将选项设置为 0 将禁用所有键打包。将其设置为DEFAULT将指示存储引擎仅打包长的CHAR、VARCHAR、BINARY或VARBINARY列。如果未使用
PACK_KEYS,则默认情况下会打包字符串,但不打包数字。如果使用PACK_KEYS=1,则数字也会被打包。打包二进制数字键时,MySQL 使用前缀压缩
每个键都需要一个额外的字节来指示前一个键中与下一个键相同的字节数。
指向行的指针按高字节优先顺序直接存储在键之后,以提高压缩率。
这意味着,如果在两行连续的行上存在许多相等的键,所有后续的“相同”键通常只占用两个字节(包括指向行的指针)。将其与普通情况进行比较,在普通情况下,后续键占用
storage_size_for_key + pointer_size(指针大小通常为 4)。相反,只有在存在许多相同的数字时,才能从前缀压缩中获得显著益处。如果所有键都完全不同,则每个键会多使用一个字节(如果键不是可以具有NULL值的键)。(在这种情况下,打包键长度存储在用于标记键是否为NULL的同一字节中。)PASSWORD此选项未被使用。
ROW_FORMAT定义存储行的物理格式。
创建禁用严格模式的表时,如果指定的行格式不受支持,则使用存储引擎的默认行格式。表的实际行格式在对
SHOW TABLE STATUS的响应中的Row_format列中报告。Create_options列显示了在CREATE TABLE语句中指定的行格式,SHOW CREATE TABLE也是如此。行格式选择因用于表的存储引擎而异。
对于
InnoDB表默认行格式由
innodb_default_row_format定义,其默认设置为DYNAMIC。当未定义ROW_FORMAT选项或使用ROW_FORMAT=DEFAULT时,使用默认行格式。如果未定义
ROW_FORMAT选项,或者使用ROW_FORMAT=DEFAULT,则重建表的运算也会静默地将表的行格式更改为innodb_default_row_format定义的默认格式。有关更多信息,请参见定义表的行格式。为了更有效地存储
InnoDB数据类型,特别是BLOB类型,请使用DYNAMIC。请参见DYNAMIC 行格式,了解与DYNAMIC行格式相关的要求。若要为
InnoDB表启用压缩,请指定ROW_FORMAT=COMPRESSED。ROW_FORMAT=COMPRESSED选项在创建临时表时不受支持。请参见第 17.9 节,“InnoDB 表和页面压缩”,了解与COMPRESSED行格式相关的要求。MySQL 早期版本中使用的行格式仍可通过指定
REDUNDANT行格式来请求。当指定非默认
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表,选项值可以是FIXED或DYNAMIC,分别代表静态或可变长度行格式。myisampack将类型设置为COMPRESSED。请参见第 18.2.3 节,“MyISAM 表存储格式”。对于
NDB表,默认ROW_FORMAT为DYNAMIC。START TRANSACTION这是一个内部使用的表选项,用于允许
CREATE TABLE ... SELECT在使用基于行的复制且存储引擎支持原子 DDL 时,在二进制日志中记录为单个原子事务。仅允许BINLOG、COMMIT和ROLLBACK语句在CREATE TABLE ... START TRANSACTION之后执行。有关相关信息,请参见第 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 TABLE或ALTER 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 节,“通用表空间”。是区分大小写的标识符。它可以带引号或不带引号。不允许使用正斜杠字符(“/”)。以“innodb_”开头的名称保留供特殊使用。tablespace_name要在系统表空间中创建表,请将
innodb_system指定为表空间名称。CREATE TABLE tbl_name ... TABLESPACE [=] innodb_system使用
TABLESPACE [=] innodb_system,无论innodb_file_per_table设置如何,您都可以将任何未压缩行格式的表放置在系统表空间中。例如,您可以使用TABLESPACE [=] innodb_system将具有ROW_FORMAT=DYNAMIC的表添加到系统表空间中。要在每个表的文件表空间中创建表,请将
innodb_file_per_table指定为表空间名称。CREATE TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table注意如果启用了
innodb_file_per_table,则无需指定TABLESPACE=innodb_file_per_table来创建InnoDB每个表的文件表空间。当启用了innodb_file_per_table时,默认情况下会在每个表的文件表空间中创建InnoDB表。允许使用
DATA DIRECTORY子句与CREATE TABLE ... TABLESPACE=innodb_file_per_table一起使用,但在其他情况下不支持与TABLESPACE子句组合使用。在DATA DIRECTORY子句中指定的目录必须为InnoDB已知。有关更多信息,请参阅使用 DATA DIRECTORY 子句。注意在
CREATE TEMPORARY TABLE中使用TABLESPACE = innodb_file_per_table和TABLESPACE = innodb_temporary子句的支持已弃用;预计将在未来版本的 MySQL 中删除它。仅与
NDB表一起使用STORAGE表选项。STORAGE确定使用的存储类型,可以是DISK或MEMORY。TABLESPACE ... STORAGE DISK将表分配给 NDB Cluster 磁盘数据表空间。STORAGE DISK不能在CREATE TABLE中使用,除非在TABLESPACEtablespace_name之前使用。对于
STORAGE MEMORY,表空间名称是可选的,因此,您可以使用TABLESPACE或仅使用tablespace_nameSTORAGE MEMORYSTORAGE MEMORY显式指定该表是内存中的。有关更多信息,请参阅第 25.6.11 节,“NDB Cluster 磁盘数据表”。
用于将一组相同的
MyISAM表作为一个表访问。这仅适用于MERGE表。请参阅第 18.7 节,“MERGE 存储引擎”。您必须对映射到
MERGE表的表具有SELECT、UPDATE和DELETE权限。注意以前,所有使用的表都必须与
MERGE表本身位于同一个数据库中。此限制不再适用。
表分区
partition_options可用于控制使用CREATE TABLE创建的表的分区。
并非本节开头partition_options语法中显示的所有选项都适用于所有分区类型。有关特定于每种类型的特定信息,请参阅以下各个类型的列表,并参阅第 26 章,分区,以获取有关 MySQL 中分区的工作原理和用途的更完整信息,以及与 MySQL 分区相关的更多表创建和其他语句示例。
可以修改、合并、添加到表以及从表中删除分区。有关执行这些任务的 MySQL 语句的基本信息,请参阅第 15.1.9 节,“ALTER TABLE 语句”。有关更详细的描述和示例,请参阅第 26.3 节,“分区管理”。
PARTITION BY如果使用,则
partition_options子句以PARTITION BY开头。此子句包含用于确定分区的函数;该函数返回一个介于 1 到num之间的整数值,其中num是分区的数量。(表可能包含的最大用户定义分区数量为 1024;本节后面讨论的子分区数量包含在此最大值中。)注意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 THAN或VALUES IN子句与PARTITION BY HASH一起使用。PARTITION BY HASH使用expr除以分区数量(即模数)的余数。有关示例和更多信息,请参阅第 26.2.4 节,“HASH 分区”。关键字
LINEAR包含一个略有不同的算法。在这种情况下,存储行的分区的编号被计算为一个或多个逻辑AND运算的结果。有关线性散列的讨论和示例,请参阅第 26.2.4.1 节,“LINEAR HASH 分区”。KEY(column_list)这类似于
HASH,除了 MySQL 提供散列函数以保证数据均匀分布外。参数column_list只是一个或多个表列的列表(最大: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;选项
ALGORITHM={1 | 2}支持[SUB]PARTITION BY [LINEAR] KEY。ALGORITHM=1会导致服务器使用与 MySQL 5.1 相同的键散列函数;ALGORITHM=2表示服务器使用在 MySQL 5.5 及更高版本中为新的KEY分区表实现并默认使用的键散列函数。(使用在 MySQL 5.5 及更高版本中使用的键散列函数创建的分区表不能由 MySQL 5.1 服务器使用。)不指定选项与使用ALGORITHM=2具有相同的效果。此选项主要用于在 MySQL 5.1 和更高版本的 MySQL 版本之间升级或降级[LINEAR] KEY分区表,或者在 MySQL 5.5 或更高版本的服务器上创建按KEY或LINEAR KEY分区的表,这些表可以在 MySQL 5.1 服务器上使用。有关更多信息,请参阅第 15.1.9.1 节,“ALTER TABLE 分区操作”。mysqldump将此选项写入版本化的注释中。
ALGORITHM=1在使用版本化注释的SHOW CREATE TABLE输出中显示(如果需要),与 mysqldump 的方式相同。即使在创建原始表时指定了此选项,ALGORITHM=2始终不会出现在SHOW CREATE TABLE输出中。您不能将
VALUES LESS THAN或VALUES IN子句与PARTITION BY KEY一起使用。RANGE(expr)在这种情况下,
expr使用一组VALUES LESS THAN运算符显示一个值范围。使用范围分区时,您必须使用VALUES LESS THAN定义至少一个分区。您不能将VALUES IN与范围分区一起使用。注意对于按
RANGE分区的表,VALUES LESS THAN必须与整数文字值或计算结果为单个整数的值的表达式一起使用。在 MySQL 8.4 中,您可以克服在使用PARTITION BY RANGE COLUMNS定义的表中的此限制,如本节后面所述。假设您有一个表,您希望根据以下方案对包含年份值的列进行分区。
分区编号 年份范围 0 1990 年及更早 1 1991 年至 1994 年 2 1995 年至 1998 年 3 1999 年至 2002 年 4 2003 年至 2005 年 5 2006 年及以后 实现此类分区方案的表可以通过此处显示的
CREATE TABLE语句来实现。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子句以类似于case部分的switch ... case块(如许多编程语言(如 C、Java 和 PHP)中发现)的方式按顺序工作。也就是说,这些子句必须以这样一种方式排列,即每个后续VALUES LESS THAN中指定的上限大于前一个上限,其中引用MAXVALUE的子句在列表中最后出现。RANGE COLUMNS(column_list)此
RANGE变体方便对使用多个列的范围条件的查询进行分区修剪(即具有WHERE a = 1 AND b < 10或WHERE a = 1 AND b = 10 AND c < 10等条件)。它允许您使用COLUMNS子句中的列列表和每个PARTITION ... VALUES LESS THAN (分区定义子句中的一组列值来指定多个列中的值范围。(在最简单的情况下,此集合包含单个列。)value_list)column_list和value_list中可以引用的最大列数为 16。COLUMNS子句中使用的column_list只能包含列名;列表中的每个列都必须是以下 MySQL 数据类型之一:整数类型;字符串类型;以及时间或日期列类型。使用BLOB、TEXT、SET、ENUM、BIT或空间数据类型的列不允许;使用浮点数类型的列也不允许。您也不能在COLUMNS子句中使用函数或算术表达式。分区定义中使用的
VALUES LESS THAN子句必须为COLUMNS()子句中出现的每个列指定文字值;也就是说,用于每个VALUES LESS THAN子句的值列表必须包含与COLUMNS子句中列出的列数量相同的数量,并且这些值的数据类型必须与这些列匹配(并且按相同顺序出现)。如果尝试在VALUES LESS THAN子句中使用的值比COLUMNS子句中的值多或少,则语句将失败,并出现错误 分区中使用列列表不一致...。您不能将NULL用于出现在VALUES 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 节“RANGE 分区” 和 第 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) );使用列表分区时,您必须使用
VALUES IN定义至少一个分区。您不能将VALUES LESS THAN与PARTITION BY LIST一起使用。注意对于按
LIST分区的表,与VALUES IN一起使用的值列表必须仅包含整数值。在 MySQL 8.4 中,您可以使用按LIST COLUMNS进行的分区来克服此限制,这将在本节后面介绍。LIST COLUMNS(column_list)此
LIST变体方便对使用多个列的比较条件的查询进行分区修剪(即具有WHERE a = 5 AND b = 5或WHERE a = 1 AND b = 10 AND c = 5等条件)。它允许您使用COLUMNS子句中的列列表和每个PARTITION ... VALUES IN (分区定义子句中的一组列值来指定多个列中的值。value_list)用于
LIST COLUMNS(中的列列表和用于column_list)VALUES IN(中的值列表的数据类型规则与用于value_list)RANGE COLUMNS(中的列列表和用于column_list)VALUES LESS THAN(中的值列表相同,只是在value_list)VALUES IN子句中,不允许使用MAXVALUE,并且可以使用NULL。与
PARTITION BY LIST相比,用于VALUES IN与PARTITION BY LIST COLUMNS一起使用的值列表之间存在一个重要区别。与PARTITION BY LIST COLUMNS一起使用时,VALUES IN子句中的每个元素都必须是列值的 集;每个集合中的值数量必须与COLUMNS子句中使用的列数量相同,并且这些值的数据类型必须与这些列匹配(并且按相同顺序出现)。在最简单的情况下,集合包含单个列。column_list中以及构成value_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) ) );PARTITIONSnum可以使用
PARTITIONS子句(其中numnum是分区数)来可选地指定分区数。如果同时使用此子句 和 任何PARTITION子句,则num必须等于使用PARTITION子句声明的任何分区的总数。注意无论您是否在创建按
RANGE或LIST分区的表时使用PARTITIONS子句,您仍然必须在表定义中包含至少一个PARTITION VALUES子句(见下文)。SUBPARTITION BY分区可以可选地划分为若干个子分区。这可以通过使用可选的
SUBPARTITION BY子句来指示。子分区可以通过HASH或KEY进行。这两个都可以是LINEAR。它们的工作方式与之前描述的等效分区类型相同。(无法按LIST或RANGE进行子分区。)可以使用
SUBPARTITIONS关键字后跟一个整数值来指示子分区的数量。对
PARTITIONS或SUBPARTITIONS子句中使用的值进行严格检查,并且此值必须遵守以下规则该值必须是正的非零整数。
不允许有前导零。
该值必须是整数文字,不能是表达式。例如,不允许使用
PARTITIONS 0.2E+01,即使0.2E+01计算结果为2。(错误 #15890)
partition_definition可以使用
partition_definition子句单独定义每个分区。构成此子句的各个部分如下PARTITIONpartition_name指定分区的逻辑名称。
VALUES对于范围分区,每个分区都必须包含一个
VALUES LESS THAN子句;对于列表分区,您必须为每个分区指定一个VALUES IN子句。这用于确定哪些行将存储在此分区中。有关语法示例,请参见 第 26 章“分区” 中的分区类型讨论。[STORAGE] ENGINEMySQL 接受
[STORAGE] ENGINE选项,用于PARTITION和SUBPARTITION。目前,使用此选项的唯一方法是将所有分区或所有子分区设置为相同的存储引擎,如果尝试为同一表中的分区或子分区设置不同的存储引擎,则会引发错误 ERROR 1469 (HY000): 此版本的 MySQL 不允许分区中混合使用处理程序.COMMENT可以使用可选的
COMMENT子句来指定描述分区的字符串。示例COMMENT = 'Data for the years previous to 1999'分区注释的最大长度为 1024 个字符。
DATA DIRECTORY和INDEX DIRECTORYDATA DIRECTORY和INDEX DIRECTORY可用于指示分别存储该分区数据和索引的目录。和data_dir都必须是绝对系统路径名。index_dir在
DATA DIRECTORY子句中指定的目录必须为InnoDB所知。有关更多信息,请参见 使用 DATA DIRECTORY 子句。您必须具有
FILE权限才能使用DATA DIRECTORY或INDEX DIRECTORY分区选项。示例
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 DIRECTORY和INDEX DIRECTORY的行为方式与CREATE TABLE语句的table_option子句中用于MyISAM表的方式相同。每个分区可以指定一个数据目录和一个索引目录。如果未指定,则数据和索引默认存储在表的数据库目录中。
如果
NO_DIR_IN_CREATE生效,则在创建分区表时将忽略DATA DIRECTORY和INDEX DIRECTORY选项。MAX_ROWS和MIN_ROWS可用于分别指定要存储在分区中的最大和最小行数。
max_number_of_rows和min_number_of_rows的值必须为正整数。与具有相同名称的表级选项一样,这些选项仅充当服务器的 “建议”,并非硬性限制。TABLESPACE可用于通过指定
TABLESPACE `innodb_file_per_table`为分区指定InnoDB文件级联表空间。所有分区必须属于相同的存储引擎。不支持将
InnoDB表分区放置在共享的InnoDB表空间中。共享表空间包括InnoDB系统表空间和通用表空间。
subpartition_definition分区定义可以选择包含一个或多个
subpartition_definition子句。每个子句至少包含SUBPARTITION,其中namename是子分区的标识符。除了将PARTITION关键字替换为SUBPARTITION之外,子分区定义的语法与分区定义的语法相同。子分区必须通过
HASH或KEY进行,并且只能在RANGE或LIST分区上进行。请参见 第 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() 的生成列是允许的。