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”。
-
LIKE
使用
CREATE TABLE ... LIKE
根据另一个表的定义创建空表,包括原表中的列属性和索引:CREATE TABLE new_tbl LIKE orig_tbl;
-
[AS]
query_expression
要从另一个表创建一个表,添加
SELECT
语句到CREATE TABLE
语句的末尾:CREATE TABLE new_tbl AS SELECT * FROM orig_tbl;
-
IGNORE | REPLACE
忽略和替换选项指示在使用
SELECT
语句复制表时,如何处理唯一键值重复行。
Column 数据类型 and Attributes
每个表的硬限制为4096列,但实际最大值取决于第10.4.7节,“表列数和行大小限制”中讨论的因素。
-
data_type
data_type
表示列定义中的数据类型。关于指定列数据类型的语法描述,以及每种类型的属性信息,请见第13章,数据类型。-
AUTO_INCREMENT
只适用于整数类型。 -
字符数据类型(
CHAR
、VARCHAR
、TEXT
类型、ENUM
、SET
和任何同义词)可以包括CHARACTER SET
来指定列的字符集。CHARSET
是CHARACTER 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,以字符为单位。对
BINARY
和VARBINARY
的长度是以字节为单位。 -
对于
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_DATE
SQL 模式,并且日期默认值不符合该模式,CREATE TABLE
在非严格 SQL 模式下产生警告,在严格模式下产生错误。例如,启用NO_ZERO_IN_DATE
,c1 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节,“服务器系统变量”。关于
InnoDB
和AUTO_INCREMENT
,请参阅第17.6.1.6节,“InnoDB 中的 AUTO_INCREMENT 处理”。关于AUTO_INCREMENT
和 MySQL 复制,请参阅第19.5.1.1节,“MySQL 复制和 AUTO_INCREMENT”。 -
COMMENT
可以使用
COMMENT
选项指定一个列的注释,长度不超过1024个字符。该注释将被SHOW CREATE TABLE
和SHOW FULL COLUMNS
语句显示。它也将在信息架构COLUMNS
表的COLUMN_COMMENT
列中显示。 -
COLUMN_FORMAT
在 NDB 集群中,也可以使用
COLUMN_FORMAT
对NDB
表的单个列指定数据存储格式。允许的列格式是FIXED
、DYNAMIC
和DEFAULT
。FIXED
用于指定固定宽度存储,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_ATTRIBUTE
和SECONDARY_ENGINE_ATTRIBUTE
选项用于指定主和副存储引擎的列属性。这些选项保留供将来使用。分配给这个选项的值是一个有效的 JSON 文档字符串或空字符串 ('')。无效的 JSON 将被拒绝。
CREATE TABLE t1 (c1 INT ENGINE_ATTRIBUTE='{"key":"value"}');
ENGINE_ATTRIBUTE
和SECONDARY_ENGINE_ATTRIBUTE
值可以重复使用,不会出现错误。在这种情况下,最后指定的值将被使用。ENGINE_ATTRIBUTE
和SECONDARY_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 KEY
或UNIQUE NOT NULL
索引,其中包含单个整数类型的列,您可以在SELECT
语句中使用_rowid
引用索引列,如唯一索引中所述。在 MySQL 中,一个
PRIMARY KEY
的名称是PRIMARY
。对于其他索引,如果您不指定名称,索引将被赋予第一个索引列的名称,带有可选的后缀(_2
、_3
、...
)以使其唯一。您可以使用SHOW INDEX FROM
查看索引名称,见第15.7.7.23节,“SHOW INDEX 语句”。tbl_name
-
KEY | INDEX
KEY
通常是INDEX
的同义词。关键字PRIMARY KEY
也可以在列定义中指定为只KEY
,这实现了与其他数据库系统的兼容性。 -
UNIQUE
一个
UNIQUE
索引创建了约束,使得索引中的所有值都必须是唯一的。如果您尝试添加一个与现有行匹配的新行,会出现错误。对于所有引擎,UNIQUE
索引允许多个NULL
值在可以包含NULL
的列中。如果您为某一列在UNIQUE
索引指定前缀值,那么该列的值必须在前缀长度内唯一。如果表有一个
PRIMARY KEY
或UNIQUE NOT NULL
索引,其中包含单个整数类型的列,您可以使用_rowid
在SELECT
语句中引用索引列,如第唯一索引 中所述。 -
FULLTEXT
A
全文索引
是一种用于全文搜索的特殊类型索引。只有InnoDB
和MyISAM
存储引擎支持全文索引
。它们只能从CHAR
,VARCHAR
, 和TEXT
列创建。索引总是对整个列进行,前缀索引不支持,如果指定了前缀长度将被忽略。见 第14.9节,“全文搜索函数”,了解操作的详细信息。可以使用WITH PARSER
子句作为索引选项
值,关联一个解析器插件,以便在全文索引和搜索操作中进行特殊处理。这一子句只对FULLTEXT
索引有效。InnoDB
和MyISAM
支持全文解析器插件。见全文搜索解析器插件和编写全文搜索解析器插件获取更多信息。 -
SPATIAL
您可以在空间数据类型上创建
SPATIAL
索引。空间类型仅支持在InnoDB
和MyISAM
表中,且索引列必须声明为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
指定可以以ASC
或DESC
结尾,指定索引值是否以升序或降序存储。如果不指定顺序specifier,默认是升序。 -
前缀,通过
length
属性定义,可以长达767个字节,对于使用REDUNDANT
或COMPACT
行格式的InnoDB表。对于使用DYNAMIC
或COMPRESSED
行格式的InnoDB表,前缀长度限制为3072个字节。对于MyISAM表,前缀长度限制为1000个字节。前缀limits以字节为单位。然而,在
CREATE TABLE
、ALTER TABLE
和CREATE INDEX
语句中的索引指定的前缀长度,对于非二进制字符串类型(CHAR
、VARCHAR
、TEXT
)被解释为字符数,对于二进制字符串类型(BINARY
、VARBINARY
、BLOB
)被解释为字节数。考虑到非二进制字符串列使用多字节字符集时指定前缀长度。 -
对
key_part
指定可以以形式(CAST
创建多值索引,用于json_path
AStype
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
只有在使用
InnoDB
和MyISAM
时,WITH PARSER
选项才能使用。它将索引与解析器插件关联,如果需要特殊处理全文检索操作。MyISAM
表具有关联的全文解析器插件,可以使用InnoDB
将表转换。 -
WITH PARSER
索引定义可以包含可选的1024个字符以内的注释。
可以使用
InnoDB
MERGE_THRESHOLD
值来为单个索引设置一个个体的值,使用index_option
COMMENT
子句。见第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 Constraints”.InnoDB
和NDB
表支持外键约束检查。被引用表的列必须总是显式命名。外键同时支持ON DELETE
和ON UPDATE
操作。更多详细信息和示例,见第15.1.20.5节,“FOREIGN KEY Constraints”.对于其他存储引擎,MySQL Server 解析并忽略
CREATE TABLE
语句中的FOREIGN KEY
语法。Important对于熟悉ANSI/ISO SQL标准的用户,请注意,没有存储引擎,包括
InnoDB
, 认识或强制执行引用完整性约束定义中的MATCH
子句。使用明确的MATCH
子句不具有指定效果,并且也会忽略ON DELETE
和ON UPDATE
子句。因此,指定MATCH
应该避免。SQL标准中的
MATCH
子句控制多列外键在比较主键时处理NULL
值的方式。InnoDB
实际实现了MATCH SIMPLE
语义,允许外键完全或部分为NULL
。在这种情况下,包含该外键的子表行可以插入,并且不匹配父表中的任何行。使用触发器也可以实现其他语义。此外,MySQL要求被引用列索引以提高性能。但是,
InnoDB
不强制要求被引用列声明为UNIQUE
或NOT NULL
。非唯一键或包含NULL
值的外键参考在操作UPDATE
或DELETE CASCADE
时处理不确定。你被建议使用只引用唯一键(或主键)且NOT NULL
的外键。MySQL解析但忽略SQL标准中的“inline
REFERENCES
specifications”(在列规范中定义),MySQL只接受独立的FOREIGN KEY
规范中的REFERENCES
子句。更多信息,请参见第1.7.2.3节,“FOREIGN KEY Constraint Differences”。 -
关于
RESTRICT
、CASCADE
、SET NULL
、NO ACTION
和SET 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允许将指定的引擎替换为默认存储引擎,而不是失败。通常情况下,这个默认值是InnoDB
default_storage_engine
系统变量的默认值。在NO_ENGINE_SUBSTITUTION
被禁用时,如果存储引擎指定不被尊重,会出现警告。 -
AUTOEXTEND_SIZE
定义了
InnoDB
当表空间满时扩展的大小。设置必须是4MB的倍数。默认设置为0,导致表空间根据隐式默认行为来扩展。更多信息,请参见第17.6.3.9节,“Tablespace AUTOEXTEND_SIZE 配置”。 -
AUTO_INCREMENT
表的初始
AUTO_INCREMENT
值。在 MySQL 8.4 中,这个值适用于MyISAM
、MEMORY
、InnoDB
和ARCHIVE
表。对于不支持AUTO_INCREMENT
表选项的引擎,可以在创建表后插入一个值小于所需值的一行“dummy”行,然后删除该行。对于支持
AUTO_INCREMENT
表选项的引擎,在CREATE TABLE
语句中,也可以使用ALTER TABLE
重置tbl_name
AUTO_INCREMENT =N
AUTO_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
将其设置为 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
选项,例如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 信息架构TABLES
表中的 TABLE_COMMENT 列中找到。该注释语法也支持
ALTER TABLE
语句对NDB
表。请注意,使用ALTER TABLE
语句时,表注释将替换之前的任何注释。在
NDB
表中,设置MERGE_THRESHOLD
选项在表注释中不受支持(被忽略)。完整语法信息和示例,请见第15.1.20.12节,“设置NDB注释选项”。
-
压缩
用于文件-per-table表空间中的InnoDB表的页面级别压缩算法。支持的值包括
Zlib
、LZ4
和None
。压缩
属性是透明页面压缩特性的引入。页面压缩仅支持在文件-per-table表空间中的InnoDB表,并且仅在支持稀疏文件和洞穿的Linux和Windows平台上可用。更多信息,请见第17.9.2节,“InnoDB页面压缩”。 -
连接
Note更早版本的MySQL使用注释选项来指定连接字符串。
-
数据目录
、索引目录
对于
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 在创建MyISAM
表时,不会根据数据库名称创建子目录。文件将被创建在指定的目录中。您必须拥有
FILE
特权以使用DATA DIRECTORY
或INDEX DIRECTORY
表选项。Important表级别的
DATA DIRECTORY
和INDEX 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 DIRECTORY
或INDEX DIRECTORY
选项的表,并且找到现有.MYD
或.MYI
文件,MyISAM总是返回错误,不会覆盖指定目录中的文件。Important您不能使用包含MySQL数据目录的路径名来指定DATA DIRECTORY或INDEX 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_ATTRIBUTE
和SECONDARY_ENGINE_ATTRIBUTE
选项用于指定主和副存储引擎的表属性。这些选项保留供将来使用。分配给这两个选项的值必须是一个有效的JSON文档字符串或空字符串 (''),无效的JSON将被拒绝。
CREATE TABLE t1 (c1 INT) ENGINE_ATTRIBUTE='{"key":"value"}';
ENGINE_ATTRIBUTE
和SECONDARY_ENGINE_ATTRIBUTE
值可以重复使用,不会出现错误。在这种情况下,最后指定的值将被使用。ENGINE_ATTRIBUTE
和SECONDARY_ENGINE_ATTRIBUTE
值不由服务器检查,也不会在更改表存储引擎时清除。 -
INSERT_METHOD
如果您想将数据插入到
MERGE
表,您必须指定要插入的表。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
表。该值被视为提示;如果必要,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 STATUS
和SHOW 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
您计划存储的表中的最大行数。这不是硬限制,而是对存储引擎的一个提示,表必须能够存储至少这个数量的行。
ImportantMAX_ROWS
和NDB
表用于控制表分区的数量已经弃用。虽然在后续版本中仍然支持,但将来可能会被删除。请使用 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
,让存储引擎只对长的CHAR
、VARCHAR
、BINARY
或VARBINARY
列进行打包。如果不使用
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
表,选项值可以是FIXED
或DYNAMIC
,用于静态或变长行格式。myisampack 将类型设置为COMPRESSED
。请参阅第18.2.3节,“MyISAM 表存储格式”。对于
NDB
表,缺省的ROW_FORMAT
是DYNAMIC
。 -
-
START TRANSACTION
这是一个内部使用表选项,用于在支持原子 DDL 的存储引擎中,以单个、原子事务方式记录
CREATE TABLE ... SELECT
语句到二进制日志,当使用行级别复制时。只允许在CREATE TABLE ... START TRANSACTION
后执行BINLOG
、COMMIT
和ROLLBACK
语句。关于相关信息,请参阅第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
要在系统表空间中创建一个表,请将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_table
和TABLESPACE = innodb_temporary
子句的支持已经废弃,预计将在 MySQL 的未来版本中删除。使用
NDB
表时,STORAGE
选项只用于确定存储类型,可以是DISK
或MEMORY
.TABLESPACE ... STORAGE DISK
将表分配到 NDB 集群磁盘数据表空间。STORAGE DISK
在CREATE TABLE
中不能单独使用,必须在TABLESPACE
tablespace_name
之前。对于
STORAGE MEMORY
,表空间名称是可选的,因此可以使用TABLESPACE
或直接使用tablespace_name
STORAGE MEMORYSTORAGE MEMORY
来明确指定该表在内存中。请参阅第25.6.11节,“NDB 集群磁盘数据表”,了解更多信息。
-
用于将多个相同的
MyISAM
表作为一个访问。只适用于MERGE
表。请参阅第18.7节,“MERGE 存储引擎”。您必须拥有对映射到
MERGE
表的表的SELECT
、UPDATE
和DELETE
权限。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 THAN
或VALUES 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] KEY
的ALGORITHM={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 服务器上使用的KEY
或LINEAR KEY
分区表。更多信息,请参见第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
与范围分区。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 < 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
子句必须为每个列指定一个字面值;即,用于每个VALUES LESS THAN
子句的值列表必须包含与在COLUMNS
子句中列出的列数相同的值。使用更多或更少值在VALUES LESS THAN
子句中将导致语句失败,错误信息为分区列表不一致...。不能使用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节,“范围分区”,和第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 THAN
与PARTITION BY LIST
。Note对于以
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
)VALUES IN
子句中不允许使用MAXVALUE
,可以使用NULL
。当使用
PARTITION BY LIST COLUMNS
时,与使用PARTITION BY LIST
的值列表不同。用于PARTITION BY LIST COLUMNS
时,每个元素都必须是set列值;每个集中的值数量必须与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) ) );
-
PARTITIONS <em class="replaceable"><code>num</code></em>
可以使用
PARTITIONS
子句指定分区数量,wherenum
num
是分区数量。如果同时使用该子句和PARTITION
子句,num
必须等于使用PARTITION
子句声明的所有分区总数。Note无论是否使用
PARTITIONS
子句在创建以RANGE
或LIST
方式分区的表,您仍然需要在表定义中包含至少一个PARTITION VALUES
子句(见下文)。 -
SUBPARTITION BY
可以将分区进一步分为多个子分区。可以使用可选的
SUBPARTITION BY
子句来表示。子分区可以通过HASH
或KEY
进行,且可以是LINEAR
。这些与之前描述的等价分区类型相同。(不可能以LIST
或RANGE
方式子分区。)SUBPARTITIONS
关键字后跟一个整数值来指定子分区数量。 -
对
PARTITIONS
或SUBPARTITIONS
子句的值进行严格检查,且该值必须遵守以下规则:-
该值必须是正整数。
-
不允许前导零。
-
该值必须是整数字面量,不能是表达式。例如,
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 对于
PARTITION
和SUBPARTITION
都接受一个[STORAGE] ENGINE
选项。当前,唯一可以使用该选项的方式是将所有分区或所有子分区设置为同一个存储引擎,并尝试在同一张表中为分区或子分区设置不同的存储引擎会raise错误ERROR 1469 (HY000): 在 MySQL 的这个版本中,分区的混杂handler不允许。 -
COMMENT
可以使用可选的
COMMENT
子句来指定分区的字符串描述。示例:COMMENT = 'Data for the years previous to 1999'
分区注释的最大长度为1024个字符。
-
DATA DIRECTORY
和INDEX DIRECTORY
DATA DIRECTORY
和INDEX DIRECTORY
可以用来指示该分区的数据和索引存储目录。同时,
和data_dir
都必须是绝对系统路径名。index_dir
指定在
DATA DIRECTORY
子句中的目录必须被InnoDB
所知。更多信息,请参见使用 DATA DIRECTORY 子句。要使用
DATA DIRECTORY
或INDEX 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 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
可以用来指定一个
InnoDB
文件每个表空间为分区,通过指定TABLESPACE `innodb_file_per_table`
。所有分区都必须属于同一个存储引擎。将
InnoDB
表分区置于共享的InnoDB
表空间中不支持。共享表空间包括InnoDB
系统表空间和一般表空间。
-
-
subpartition_definition
分区定义可选地包含一个或多个
subpartition_definition
子句。每个这些子句至少包含SUBPARTITION
,其中name
name
是子分区的标识符。除了将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()
定义的生成列是允许的。