CREATE TABLE

语法说明

CREATE TABLE 语句用于在当前所选数据库创建一张新表。

语法结构

  1. > CREATE [TEMPORARY] TABLE [IF NOT EXISTS] [db.]table_name [comment = "comment of table"];
  2. (
  3. name1 type1 [comment 'comment of column'] [AUTO_INCREMENT] [[PRIMARY] KEY] [[FOREIGN] KEY],
  4. name2 type2 [comment 'comment of column'],
  5. ...
  6. )
  7. [cluster by (column_name1, column_name2, ...);]
  8. [partition_options]

语法释义

TEMPORARY

在创建表时,可以使用 TEMPORARY 关键字创建一个临时表。TEMPORARY 表只在当前会话中可见,在会话关闭时自动删除。这表示两个不同的会话可以使用相同的临时表名,而不会彼此冲突或与同名的现有非临时表冲突。(在删除临时表之前,会隐藏现有表。)

删除数据库会自动删除数据库中创建的所有 TEMPORARY 表。

创建会话可以对表执行任何操作,例如 DROP tableINSERTUPDATESELECT

COMMENT

可以使用 comment 选项指定列或整张表的注释:

  • CREATE TABLE [IF NOT EXISTS] [db.]table_name [comment = "comment of table"]; 中的 comment 为整张表的注释,最长 2049 个字符。
  • (name1 type1 [comment 'comment of column'],...) 中的 comment 为指定列的注释:最长 1024 个字符。

使用 SHOW CREATE TABLESHOW FULL COLUMNS 语句显示注释内容。注释内容也显示在 INFORMATION_SCHEMA.COLUMN_COMMENT 列中。

AUTO_INCREMENT

AUTO_INCREMENT:表的初始值,初始值从 1 开始,且数据列的值必须唯一。

  • 设置 AUTO_INCREMENT 的列,需为整数或者浮点数据类型。
  • 自增列需要设置为 NOT NULL,否则会直接存储 NULL。当你将 NULL(推荐)或 0 值插入索引的 AUTO_INCREMENT 列时,该列将设置为下一个序列值。通常这是 value+1,其中 value 是表中当前列的最大值。

  • 每个表只能有一个 AUTO_INCREMENT 列,它必须可以被索引,且不能设置默认值。AUTO_INCREMENT 列需要含有正数值,如果插入一个负数被判断为插入一个非常大的正数,这样做是为了避免数字出现精度问题,并确保不会意外出现包含 0 的 AUTO_INCREMENT 列。

PRIMARY KEY

PRIMARY KEY 即主键约束,用于唯一标示表中的每条数据。 主键必须包含 UNIQUE 值,不能包含 NULL 值。 当前版本一个表只能有一个主键,并且这个主键只能有一个列组成。

  • 在建表时创建主键

以下 SQL 语句在创建 Persons 表时,在其中的 ID 列创建主键:

  1. > CREATE TABLE Persons (
  2. ID int NOT NULL,
  3. LastName varchar(255) NOT NULL,
  4. FirstName varchar(255),
  5. Age int,
  6. PRIMARY KEY (ID)
  7. );

Note

上述示例中只有一个主键 PK_Person,并且其中仅包含了一列(ID

例如使用如下建表语句时会有错误:

  1. > CREATE TABLE Students (
  2. ID int NOT NULL,
  3. LastName varchar(255) NOT NULL,
  4. FirstName varchar(255),
  5. Age int,
  6. PRIMARY KEY (ID,LastName)
  7. );
  8. ERROR 1105 (HY000): tae catalog: schema validation: compound idx not supported yet

FOREIGN KEY

FOREIGN KEY 约束,即外键约束,是表的一个特殊字段,经常与主键约束一起使用。外键约束是用于防止破坏表之间链接的行为。对于两个具有关联关系的表而言,相关联字段中主键所在的表就是主表(父表),外键所在的表就是从表(子表)。外键用来建立主表与从表的关联关系,为两个表的数据建立连接,约束两个表中数据的一致性和完整性。

FOREIGN KEY 约束也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。

定义外键时,需要遵守下列规则:

  • 主表必须已经存在于数据库中,或者是当前正在创建的表。如果是后一种情况,则主表与从表是同一个表,这样的表称为自参照表,这种结构称为自参照完整性。
  • 必须为主表定义主键。

  • 在主表的表名后面指定列名或列名的组合。这个列或列的组合必须是主表的主键或候选键。

  • 外键中列的数目必须和主表的主键中列的数目相同。

  • 外键中列的数据类型必须和主表主键中对应列的数据类型相同。

下面通过一个例子进行说明通过 FOREIGN KEY 和 PRIMARY KEY 关联父表与子表:

首先创建一个父表,字段 a 为主键:

  1. create table t1(a int primary key,b varchar(5));
  2. insert into t1 values(101,'abc'),(102,'def');
  3. mysql> select * from t1;
  4. +------+------+
  5. | a | b |
  6. +------+------+
  7. | 101 | abc |
  8. | 102 | def |
  9. +------+------+
  10. 2 rows in set (0.00 sec)

然后创建一个子表,字段 c 为外键,关联父表字段 a:

  1. create table t2(a int ,b varchar(5),c int, foreign key(c) references t1(a));
  2. insert into t2 values(1,'zs1',101),(2,'zs2',102);
  3. insert into t2 values(3,'xyz',null);
  4. mysql> select * from t2;
  5. +------+------+------+
  6. | a | b | c |
  7. +------+------+------+
  8. | 1 | zs1 | 101 |
  9. | 2 | zs2 | 102 |
  10. | 3 | xyz | NULL |
  11. +------+------+------+
  12. 3 rows in set (0.00 sec)

有关数据完整性约束的更多信息,参见数据完整性约束概述

Cluster by

Cluster by 是一种用于优化表的物理排列方式的命令。在建表时使用 Cluster by 命令,对于无主键的表,可以按照指定的列对表进行物理排序,并将数据行重新排列成与该列的值的顺序相同的顺序。使用 Cluster by 提高查询性能。

  • 单列语法为:create table() cluster by col;
  • 多列语法为:create table() cluster by (col1, col2);

Note: Cluster by 不能和主键同时存在,否则会语法报错;Cluster by 只能在建表时指定,不支持动态创建。

更多关于使用 Cluster by 进行性能调优,参见使用 Cluster by 语句调优.

Table PARTITION 和 PARTITIONS

  1. partition_options:
  2. PARTITION BY
  3. { [LINEAR] HASH(expr)
  4. | [LINEAR] KEY [ALGORITHM={1 | 2}] (column_list)
  5. [PARTITIONS num]
  6. [(partition_definition [, partition_definition] ...)]
  7. partition_definition:
  8. PARTITION partition_name
  9. [VALUES
  10. {LESS THAN {(expr | value_list) | MAXVALUE}
  11. |
  12. IN (value_list)}]
  13. [COMMENT [=] 'string' ]

分区可以被修改、合并、添加到表中,也可以从表中删除。

· 和单个磁盘或文件系统分区相比,可以存储更多的数据。

· 优化查询。

  • where 子句中包含分区条件时,可以只扫描必要的分区。
  • 涉及聚合函数的查询时,可以容易的在每个分区上并行处理,最终只需汇总得到结果。

· 对于已经过期或者不需要保存的数据,可以通过删除与这些数据有关的分区来快速删除数据。

· 跨多个磁盘来分散数据查询,以获得更大的查询吞吐量。

  • PARTITION BY

分区语法以 PARTITION BY 开头。该子句包含用于确定分区的函数,这个函数返回一个从 1 到 num 的整数值,其中 num 是分区的数目。

  • HASH(expr)

在实际工作中经常遇到像会员表的没有明显可以分区的特征字段的大表。为了把这类的数据进行分区打散,MatrixOne 提供了 HASH 分区。基于给定的分区个数,将数据分配到不同的分区,HASH 分区只能针对整数进行 HASH,对于非整形的字段则通过表达式将其转换成整数。

· HASH 分区,基于给定的分区个数,把数据分配到不同的分区。

· Expr 是使用一个或多个表列的表达式。

示例如下:

  1. CREATE TABLE t1 (col1 INT, col2 CHAR(5))
  2. PARTITION BY HASH(col1);
  3. CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME)
  4. PARTITION BY HASH ( YEAR(col3) );
  • KEY(column_list)

· KEY 分区,按照某个字段取余。分区对象必须为列,不能是基于列的表达式,且允许多列,KEY 分区列可以不指定,默认为逐渐或者唯一键,不指定的情况下,则必须显性指定列。

类似于 HASHcolumn_list 参数只是一个包含 1 个或多个表列的列表(最大值:16)。下面的示例为一个按 KEY 分区的简单表,有 4 个分区:

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

对于按 KEY 分区的表,可以使用 LINEAR KEY 来进行线性分区。这与使用 HASH 分区的表具有相同的效果。下面的示例为使用 LINEAR KEY 线性分区在 5 个分区之间分配数据:

  1. CREATE TABLE tk (col1 INT, col2 CHAR(5), col3 DATE)
  2. PARTITION BY LINEAR KEY(col3)
  3. PARTITIONS 5;
  • PARTITIONS num

可以选择使用 PARTITIONS num 子句指定分区数,其中 num 是分区数。如果使用此子句的同时,也使用了其他 PARTITION 子句,那么 num 必须等于使用 PARTITION 子句声明的分区的总数。

示例

  • 示例 1:创建普通表
  1. CREATE TABLE test(a int, b varchar(10));
  2. INSERT INTO test values(123, 'abc');
  3. mysql> SELECT * FROM test;
  4. +------+---------+
  5. | a | b |
  6. +------+---------+
  7. | 123 | abc |
  8. +------+---------+
  • 示例 2:创建表示增加注释
  1. create table t2 (a int, b int) comment = "事实表";
  2. mysql> show create table t2;
  3. +-------+---------------------------------------------------------------------------------------+
  4. | Table | Create Table |
  5. +-------+---------------------------------------------------------------------------------------+
  6. | t2 | CREATE TABLE `t2` (
  7. `a` INT DEFAULT NULL,
  8. `b` INT DEFAULT NULL
  9. ) COMMENT='事实表', |
  10. +-------+---------------------------------------------------------------------------------------+
  • 示例 3:建表时为列增加注释
  1. create table t3 (a int comment '列的注释', b int) comment = "table";
  2. mysql> SHOW CREATE TABLE t3;
  3. +-------+----------------------------------------------------------------------------------------------------------+
  4. | Table | Create Table |
  5. +-------+----------------------------------------------------------------------------------------------------------+
  6. | t3 | CREATE TABLE `t3` (
  7. `a` INT DEFAULT NULL COMMENT '列的注释',
  8. `b` INT DEFAULT NULL
  9. ) COMMENT='table', |
  10. +-------+----------------------------------------------------------------------------------------------------------+
  • 示例 4:创建普通分区表
  1. CREATE TABLE tp1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY KEY(col3) PARTITIONS 4;
  2. mysql> SHOW CREATE TABLE tp1;
  3. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
  4. | Table | Create Table |
  5. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
  6. | tp1 | CREATE TABLE `tp1` (
  7. `col1` INT DEFAULT NULL,
  8. `col2` CHAR(5) DEFAULT NULL,
  9. `col3` DATE DEFAULT NULL
  10. ) partition by key algorithm = 2 (col3) partitions 4 |
  11. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------+
  12. 1 row in set (0.00 sec)
  13. -- 不指定分区数
  14. CREATE TABLE tp2 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY KEY(col3);
  15. mysql> SHOW CREATE TABLE tp2;
  16. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  17. | Table | Create Table |
  18. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  19. | tp2 | CREATE TABLE `tp2` (
  20. `col1` INT DEFAULT NULL,
  21. `col2` CHAR(5) DEFAULT NULL,
  22. `col3` DATE DEFAULT NULL
  23. ) partition by key algorithm = 2 (col3) |
  24. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  25. 1 row in set (0.00 sec)
  26. -- 指定分区算法
  27. CREATE TABLE tp3
  28. (
  29. col1 INT,
  30. col2 CHAR(5),
  31. col3 DATE
  32. ) PARTITION BY KEY ALGORITHM = 1 (col3);
  33. mysql> show create table tp3;
  34. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  35. | Table | Create Table |
  36. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  37. | tp3 | CREATE TABLE `tp3` (
  38. `col1` INT DEFAULT NULL,
  39. `col2` CHAR(5) DEFAULT NULL,
  40. `col3` DATE DEFAULT NULL
  41. ) partition by key algorithm = 1 (col3) |
  42. +-------+---------------------------------------------------------------------------------------------------------------------------------------------+
  43. 1 row in set (0.00 sec)
  44. -- 指定分区算法及分区数
  45. CREATE TABLE tp4 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY LINEAR KEY ALGORITHM = 1 (col3) PARTITIONS 5;
  46. mysql> SHOW CREATE TABLE tp4;
  47. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  48. | Table | Create Table |
  49. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  50. | tp4 | CREATE TABLE `tp4` (
  51. `col1` INT DEFAULT NULL,
  52. `col2` CHAR(5) DEFAULT NULL,
  53. `col3` DATE DEFAULT NULL
  54. ) partition by linear key algorithm = 1 (col3) partitions 5 |
  55. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  56. 1 row in set (0.01 sec)
  57. -- 多列分区
  58. CREATE TABLE tp5
  59. (
  60. col1 INT,
  61. col2 CHAR(5),
  62. col3 DATE
  63. ) PARTITION BY KEY(col1, col2) PARTITIONS 4;
  64. mysql> SHOW CREATE TABLE tp5;
  65. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  66. | Table | Create Table |
  67. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  68. | tp5 | CREATE TABLE `tp5` (
  69. `col1` INT DEFAULT NULL,
  70. `col2` CHAR(5) DEFAULT NULL,
  71. `col3` DATE DEFAULT NULL
  72. ) partition by key algorithm = 2 (col1, col2) partitions 4 |
  73. +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
  74. 1 row in set (0.01 sec)
  75. -- 创建主键列分区
  76. CREATE TABLE tp6
  77. (
  78. col1 INT NOT NULL PRIMARY KEY,
  79. col2 DATE NOT NULL,
  80. col3 INT NOT NULL,
  81. col4 INT NOT NULL
  82. ) PARTITION BY KEY(col1) PARTITIONS 4;
  83. mysql> SHOW CREATE TABLE tp6;
  84. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  85. | Table | Create Table |
  86. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  87. | tp6 | CREATE TABLE `tp6` (
  88. `col1` INT NOT NULL,
  89. `col2` DATE NOT NULL,
  90. `col3` INT NOT NULL,
  91. `col4` INT NOT NULL,
  92. PRIMARY KEY (`col1`)
  93. ) partition by key algorithm = 2 (col1) partitions 4 |
  94. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  95. 1 row in set (0.01 sec)
  96. -- 创建HASH分区
  97. CREATE TABLE tp7
  98. (
  99. col1 INT,
  100. col2 CHAR(5)
  101. ) PARTITION BY HASH(col1);
  102. mysql> SHOW CREATE TABLE tp7;
  103. +-------+------------------------------------------------------------------------------------------------------+
  104. | Table | Create Table |
  105. +-------+------------------------------------------------------------------------------------------------------+
  106. | tp7 | CREATE TABLE `tp7` (
  107. `col1` INT DEFAULT NULL,
  108. `col2` CHAR(5) DEFAULT NULL
  109. ) partition by hash (col1) |
  110. +-------+------------------------------------------------------------------------------------------------------+
  111. 1 row in set (0.01 sec)
  112. -- 创建 HASH 分区时指定分区数
  113. CREATE TABLE tp8
  114. (
  115. col1 INT,
  116. col2 CHAR(5)
  117. ) PARTITION BY HASH(col1) PARTITIONS 4;
  118. mysql> SHOW CREATE TABLE tp8;
  119. +-------+-------------------------------------------------------------------------------------------------------------------+
  120. | Table | Create Table |
  121. +-------+-------------------------------------------------------------------------------------------------------------------+
  122. | tp8 | CREATE TABLE `tp8` (
  123. `col1` INT DEFAULT NULL,
  124. `col2` CHAR(5) DEFAULT NULL
  125. ) partition by hash (col1) partitions 4 |
  126. +-------+-------------------------------------------------------------------------------------------------------------------+
  127. 1 row in set (0.00 sec)
  128. -- 创建分区时,指定分区粒度
  129. CREATE TABLE tp9
  130. (
  131. col1 INT,
  132. col2 CHAR(5),
  133. col3 DATETIME
  134. ) PARTITION BY HASH (YEAR(col3));
  135. mysql> SHOW CREATE TABLE tp9;
  136. +-------+------------------------------------------------------------------------------------------------------------------------------------------+
  137. | Table | Create Table |
  138. +-------+------------------------------------------------------------------------------------------------------------------------------------------+
  139. | tp9 | CREATE TABLE `tp9` (
  140. `col1` INT DEFAULT NULL,
  141. `col2` CHAR(5) DEFAULT NULL,
  142. `col3` DATETIME DEFAULT NULL
  143. ) partition by hash (year(col3)) |
  144. +-------+------------------------------------------------------------------------------------------------------------------------------------------+
  145. 1 row in set (0.00 sec)
  146. -- 创建分区时,指定分区粒度和分区数量
  147. CREATE TABLE tp10
  148. (
  149. col1 INT,
  150. col2 CHAR(5),
  151. col3 DATE
  152. ) PARTITION BY LINEAR HASH( YEAR(col3)) PARTITIONS 6;
  153. mysql> SHOW CREATE TABLE tp10;
  154. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
  155. | Table | Create Table |
  156. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
  157. | tp10 | CREATE TABLE `tp10` (
  158. `col1` INT DEFAULT NULL,
  159. `col2` CHAR(5) DEFAULT NULL,
  160. `col3` DATE DEFAULT NULL
  161. ) partition by linear hash (year(col3)) partitions 6 |
  162. +-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------+
  163. 1 row in set (0.00 sec)
  164. -- 创建分区时,使用主键列作为 HASH 分区
  165. CREATE TABLE tp12 (col1 INT NOT NULL PRIMARY KEY, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL) PARTITION BY HASH(col1) PARTITIONS 4;
  166. mysql> SHOW CREATE TABLE tp12;
  167. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  168. | Table | Create Table |
  169. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  170. | tp12 | CREATE TABLE `tp12` (
  171. `col1` INT NOT NULL,
  172. `col2` DATE NOT NULL,
  173. `col3` INT NOT NULL,
  174. `col4` INT NOT NULL,
  175. PRIMARY KEY (`col1`)
  176. ) partition by hash (col1) partitions 4 |
  177. +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
  178. 1 row in set (0.01 sec)
  • 示例 5:主键自增
  1. drop table if exists t1;
  2. create table t1(a bigint primary key auto_increment, b varchar(10));
  3. insert into t1(b) values ('bbb');
  4. insert into t1 values (3, 'ccc');
  5. insert into t1(b) values ('bbb1111');
  6. mysql> select * from t1 order by a;
  7. +------+---------+
  8. | a | b |
  9. +------+---------+
  10. | 1 | bbb |
  11. | 3 | ccc |
  12. | 4 | bbb1111 |
  13. +------+---------+
  14. 3 rows in set (0.01 sec)
  15. insert into t1 values (2, 'aaaa1111');
  16. mysql> select * from t1 order by a;
  17. +------+----------+
  18. | a | b |
  19. +------+----------+
  20. | 1 | bbb |
  21. | 2 | aaaa1111 |
  22. | 3 | ccc |
  23. | 4 | bbb1111 |
  24. +------+----------+
  25. 4 rows in set (0.00 sec)
  26. insert into t1(b) values ('aaaa1111');
  27. mysql> select * from t1 order by a;
  28. +------+----------+
  29. | a | b |
  30. +------+----------+
  31. | 1 | bbb |
  32. | 2 | aaaa1111 |
  33. | 3 | ccc |
  34. | 4 | bbb1111 |
  35. | 5 | aaaa1111 |
  36. +------+----------+
  37. 5 rows in set (0.01 sec)
  38. insert into t1 values (100, 'xxxx');
  39. insert into t1(b) values ('xxxx');
  40. mysql> select * from t1 order by a;
  41. +------+----------+
  42. | a | b |
  43. +------+----------+
  44. | 1 | bbb |
  45. | 2 | aaaa1111 |
  46. | 3 | ccc |
  47. | 4 | bbb1111 |
  48. | 5 | aaaa1111 |
  49. | 100 | xxxx |
  50. | 101 | xxxx |
  51. +------+----------+
  52. 7 rows in set (0.00 sec)

限制

目前不支持使用 ALTER TABLE table_name DROP PRIMARY KEY 语句删除表中的主键。