PingKai Logo下载

CREATE TABLE

CREATE TABLE 语句用于在当前所选数据库中创建新表,与 MySQL 中 CREATE TABLE 语句的行为类似。另可参阅单独的 CREATE TABLE LIKE 文档。

语法图

CreateTableStmt
CREATE OptTemporary TABLE IfNotExists TableName TableElementListOpt CreateTableOptionListOpt PartitionOpt DuplicateOpt AsOpt CreateTableSelectOpt LikeTableWithOrWithoutParen OnCommitOpt
OptTemporary
TEMPORARY GLOBAL TEMPORARY
IfNotExists
IF NOT EXISTS
TableName
Identifier . Identifier
TableElementListOpt
( TableElementList )
TableElementList
TableElement ,
TableElement
ColumnDef Constraint
ColumnDef
ColumnName Type SERIAL ColumnOptionListOpt
ColumnOptionListOpt
ColumnOption
ColumnOptionList
ColumnOption
ColumnOption
NOT NULL AUTO_INCREMENT PrimaryOpt KEY GLOBAL LOCAL UNIQUE KEY GLOBAL LOCAL DEFAULT DefaultValueExpr SERIAL DEFAULT VALUE ON UPDATE NowSymOptionFraction COMMENT stringLit ConstraintKeywordOpt CHECK ( Expression ) EnforcedOrNotOrNotNullOpt GeneratedAlways AS ( Expression ) VirtualOrStored ReferDef COLLATE CollationName COLUMN_FORMAT ColumnFormat STORAGE StorageMedia AUTO_RANDOM OptFieldLen
Constraint
IndexDef ForeignKeyDef
IndexDef
INDEX KEY IndexName ( KeyPartList ) IndexOption
KeyPartList
KeyPart ,
KeyPart
ColumnName ( Length ) ASC DESC ( Expression ) ASC DESC
IndexOption
COMMENT String VISIBLE INVISIBLE USING TYPE BTREE RTREE HASH GLOBAL LOCAL
ForeignKeyDef
CONSTRAINT Identifier FOREIGN KEY Identifier ( ColumnName , ) REFERENCES TableName ( ColumnName , ) ON DELETE ReferenceOption ON UPDATE ReferenceOption
ReferenceOption
RESTRICT CASCADE SET NULL SET DEFAULT NO ACTION
CreateTableOptionListOpt
TableOptionList
PartitionOpt
PARTITION BY PartitionMethod PartitionNumOpt SubPartitionOpt PartitionDefinitionListOpt
DuplicateOpt
IGNORE REPLACE
TableOptionList
TableOption ,
TableOption
PartDefOption DefaultKwdOpt CharsetKw EqOpt CharsetName COLLATE EqOpt CollationName AUTO_INCREMENT AUTO_ID_CACHE AUTO_RANDOM_BASE AVG_ROW_LENGTH CHECKSUM TABLE_CHECKSUM KEY_BLOCK_SIZE DELAY_KEY_WRITE SHARD_ROW_ID_BITS PRE_SPLIT_REGIONS EqOpt LengthNum CONNECTION PASSWORD COMPRESSION EqOpt stringLit RowFormat STATS_PERSISTENT PACK_KEYS EqOpt StatsPersistentVal STATS_AUTO_RECALC STATS_SAMPLE_PAGES EqOpt LengthNum DEFAULT STORAGE MEMORY DISK SECONDARY_ENGINE EqOpt NULL StringName UNION EqOpt ( TableNameListOpt ) ENCRYPTION EqOpt EncryptionOpt TTL EqOpt TimeColumnName + INTERVAL Expression TimeUnit TTLEnable EqOpt ON OFF TTLJobInterval EqOpt stringLit PlacementPolicyOption
OnCommitOpt
ON COMMIT DELETE ROWS
PlacementPolicyOption
PLACEMENT POLICY EqOpt PolicyName PLACEMENT POLICY EqOpt SET DEFAULT

TiDB 支持以下 table_option。TiDB 会解析并忽略其他 table_option 参数,例如 AVG_ROW_LENGTHCHECKSUMCOMPRESSIONCONNECTIONDELAY_KEY_WRITEENGINEKEY_BLOCK_SIZEMAX_ROWSMIN_ROWSROW_FORMATSTATS_PERSISTENT

参数含义举例
AUTO_INCREMENT自增字段初始值AUTO_INCREMENT = 5
SHARD_ROW_ID_BITS用来设置隐式 _tidb_rowid 的分片数量的 bit 位数SHARD_ROW_ID_BITS = 4
PRE_SPLIT_REGIONS用来在建表时预先均匀切分 2^(PRE_SPLIT_REGIONS) 个 RegionPRE_SPLIT_REGIONS = 4
AUTO_ID_CACHE用来指定 Auto ID 在 TiDB 实例中 Cache 的大小,默认情况下 TiDB 会根据 Auto ID 分配速度自动调整AUTO_ID_CACHE = 200
AUTO_RANDOM_BASE用来指定 AutoRandom 自增部分的初始值,该参数可以被认为属于内部接口的一部分,对于用户而言请忽略AUTO_RANDOM_BASE = 0
CHARACTER SET指定该表所使用的字符集CHARACTER SET = 'utf8mb4'
COLLATE指定该表所使用的字符集排序规则COLLATE = 'utf8mb4_bin'
COMMENT注释信息COMMENT = 'comment info'

默认情况下,表注释最大为 2048 字节,列注释最大为 1024 字节。可以通过系统变量 pkdb_comment_byte_length_limit 调整表注释和列注释的最大字节长度。

CREATE TABLE ... AS SELECT

CREATE TABLE ... AS SELECT(CTAS)语句会根据查询结果创建并填充新表。与 CREATE TABLE LIKE 不同,CTAS 不会直接复制源表的索引或约束,而是根据 SELECT 的输出列生成目标表结构并写入数据。

CREATE TABLE [IF NOT EXISTS] tbl_name
    [(create_definition,...)]
    [table_options]
    [IGNORE | REPLACE]
    [AS] query_expression
  • AS 关键字可省略。
  • query_expression 可以是普通 SELECT、包含 UNION 的查询、子查询、包含窗口函数的查询,或者 TABLE tbl_name
  • 如果未显式指定 create_definition,TiDB 会根据 SELECT 的输出列推导目标表的列定义,列顺序与查询输出顺序一致。
  • 如果显式指定了 create_definition,同名列优先使用 CREATE TABLE 中的定义;只在 CREATE TABLE 中出现的列会排在最前面,并使用默认值或 NULL 填充。如果这类列声明为 NOT NULL 且没有默认值,语句会报错。
  • 对于直接来自源表的列,TiDB 会尽量继承其类型、NULL 属性和默认值;但不会自动继承 PRIMARY KEYUNIQUE INDEX、普通索引或 AUTO_INCREMENT 属性。如需保留这些属性,需要在 CREATE TABLE 部分显式声明,这些行为与 MySQL 8.0 一致。
  • 执行 CTAS 需要对目标表所在数据库具有 CREATEINSERT 权限,并对查询涉及的源对象具有 SELECT 权限。

CTAS 相关系统变量

  • tidb_create_from_select_using_import 用于控制 CTAS 的写入路径:
    • 设置为 ON 时,CTAS 使用 IMPORT INTO 路径写入目标表。
    • 设置为 OFF 时,CTAS 使用 INSERT 路径写入目标表。
  • 当 CTAS 使用 INSERT 路径且数据量较大时,可能触发单条查询占用内存限制:
ERROR 8175 (HY000): Your query has been cancelled due to exceeding the allowed memory limit for a single SQL query. Please try narrowing your query scope or increase the tidb_mem_quota_query limit and try again.[conn=0]
  • 对于这一场景,更合适的做法不是直接提高 tidb_mem_quota_query,而是开启 batch DML,将 INSERT 路径拆分为多个批次执行,以降低单批次写入的内存峰值。
  • 可以按如下方式设置相关变量:
SET @@global.tidb_enable_batch_dml = 1;
SET @@session.tidb_batch_insert = 1;
SET @@session.tidb_dml_batch_size = 1000000;
  • 上述变量的作用如下:
  • 使用 batch DML 时,单条 CTAS 语句的写入会被拆分为多个事务提交,不再保证原子性。因此,建议仅在明确接受这一行为时使用。

CTAS 示例

先准备源表 foo

DROP TABLE IF EXISTS foo, bar;
CREATE TABLE foo (n INT);
INSERT INTO foo VALUES (1);

准备完成后,foo 中的数据如下:

tidb> SELECT * FROM foo;
+------+
| n    |
+------+
|    1 |
+------+
1 row in set (0.003 sec)

CREATE TABLE 部分声明了额外列时,这些列会排在结果表前面,并以默认值或 NULL 填充:

CREATE TABLE bar (m INT) SELECT n FROM foo;

执行后,bar 中的数据如下:

tidb> CREATE TABLE bar (m INT) SELECT n FROM foo;
Query OK, 0 rows affected (1.597 sec)

tidb> SELECT * FROM bar;
+------+------+
| m    | n    |
+------+------+
| NULL |    1 |
+------+------+
1 row in set (0.004 sec)

CREATE TABLE ... SELECT 不会自动创建索引。如需索引,需要在 SELECT 之前显式声明:

DROP TABLE IF EXISTS bar;
CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

执行后,bar 的表结构如下:

tidb> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
Query OK, 0 rows affected (1.590 sec)

tidb> SHOW CREATE TABLE bar\G
*************************** 1. row ***************************
       Table: bar
Create Table: CREATE TABLE `bar` (
  `n` int DEFAULT NULL,
  UNIQUE KEY `n` (`n`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1 row in set (0.001 sec)

除了 SELECT 之外,也可以用 TABLE 语句作为 CTAS 的数据来源。以下示例先准备源表 t1

DROP TABLE IF EXISTS t1, tt1, tt2;
CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (1, 2), (6, 7), (10, -4), (14, 6);

使用 TABLE t1 创建新表 tt1

CREATE TABLE tt1 TABLE t1;

执行后,tt1 中的数据如下:

tidb> TABLE tt1;
+------+------+
| a    | b    |
+------+------+
|    1 |    2 |
|    6 |    7 |
|   10 |   -4 |
|   14 |    6 |
+------+------+
4 rows in set (0.004 sec)

示例

创建一张简单表并插入一行数据:

CREATE TABLE t1 (a int);
DESC t1;
SHOW CREATE TABLE t1\G
INSERT INTO t1 (a) VALUES (1);
SELECT * FROM t1;
mysql> drop table if exists t1;
Query OK, 0 rows affected (0.23 sec)

mysql> CREATE TABLE t1 (a int);
Query OK, 0 rows affected (0.09 sec)

mysql> DESC t1;
+-------+------+------+------+---------+-------+
| Field | Type | Null | Key  | Default | Extra |
+-------+------+------+------+---------+-------+
| a     | int  | YES  |      | NULL    |       |
+-------+------+------+------+---------+-------+
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `a` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1 row in set (0.00 sec)

mysql> INSERT INTO t1 (a) VALUES (1);
Query OK, 1 row affected (0.03 sec)

mysql> SELECT * FROM t1;
+------+
| a    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

删除一张表。如果该表不存在,就建一张表:

DROP TABLE IF EXISTS t1;
CREATE TABLE IF NOT EXISTS t1 (
 id BIGINT NOT NULL PRIMARY KEY auto_increment,
 b VARCHAR(200) NOT NULL
);
DESC t1;
mysql> DROP TABLE IF EXISTS t1;
Query OK, 0 rows affected (0.22 sec)
mysql> CREATE TABLE IF NOT EXISTS t1 (
          id BIGINT NOT NULL PRIMARY KEY auto_increment,
          b VARCHAR(200) NOT NULL
         );
Query OK, 0 rows affected (0.08 sec)
mysql> DESC t1;
+-------+--------------+------+------+---------+----------------+
| Field | Type         | Null | Key  | Default | Extra          |
+-------+--------------+------+------+---------+----------------+
| id    | bigint       | NO   | PRI  | NULL    | auto_increment |
| b     | varchar(200) | NO   |      | NULL    |                |
+-------+--------------+------+------+---------+----------------+
2 rows in set (0.00 sec)

MySQL 兼容性

TiDB 不支持以 VALUES 语句作为 CREATE TABLE ... SELECT 的数据来源。

  • 支持除空间类型以外的所有数据类型。
  • 为了兼容 MySQL,TiDB 在语法上支持 HASHBTREERTREE 等索引类型,但会忽略它们。
  • TiDB 支持解析 FULLTEXT 语法,但不支持使用 FULLTEXT 索引。
  • 为了与 MySQL 兼容,index_col_name 属性支持 length 选项,最大长度默认限制为 3072 字节。此长度限制可以通过配置项 max-index-length 更改,具体请参阅 TiDB 配置文件描述
  • 为了与 MySQL 兼容,TiDB 会解析但忽略 index_col_name 属性的 [ASC | DESC] 索引排序选项。
  • COMMENT 属性不支持 WITH PARSER 选项。
  • TiDB 在单个表中默认支持 1017 列,最大可支持 4096 列。InnoDB 中相应的数量限制为 1017 列,MySQL 中的硬限制为 4096 列。详情参阅 TiDB 使用限制
  • 分区表支持 HASHRANGELISTKEY 分区类型。对于不支持的分区类型,TiDB 会报 Warning: Unsupported partition type %s, treat as normal table 错误,其中 %s 为不支持的具体分区类型。
  • TiDB 对分区表进行了扩展。你可以指定 GLOBAL 索引选项将 PRIMARY KEYUNIQUE INDEX 设置为全局索引。该扩展与 MySQL 不兼容。

另请参阅