From ac71055fa1678d8b9ad470a98631ff0daec89707 Mon Sep 17 00:00:00 2001 From: ti-srebot <66930949+ti-srebot@users.noreply.github.com> Date: Thu, 24 Sep 2020 16:08:38 +0800 Subject: [PATCH] constraints, create table: improve clarity and update out of date info (#4447) (#4584) * cherry pick #4447 to release-3.1 Signed-off-by: ti-srebot * resolve * Update sql-statements/sql-statement-create-table.md Co-authored-by: TomShawn <41534398+TomShawn@users.noreply.github.com> --- constraints.md | 20 ++ sql-statements/sql-statement-create-table.md | 256 +++++-------------- 2 files changed, 80 insertions(+), 196 deletions(-) diff --git a/constraints.md b/constraints.md index 6cfe624d5407..92300aa3cd86 100644 --- a/constraints.md +++ b/constraints.md @@ -167,6 +167,26 @@ Query OK, 0 rows affected (0.10 sec) 除上述规则外,TiDB 还强加了另一个限制,即一旦一张表创建成功,其主键就不能再改变。 +## `CHECK` 约束 + +TiDB 会解析并忽略 `CHECK` 约束。该行为与 MySQL 5.7 的相兼容。 + +示例如下: + +{{< copyable "sql" >}} + +```sql +DROP TABLE IF EXISTS users; +CREATE TABLE users ( + id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, + username VARCHAR(60) NOT NULL, + UNIQUE KEY (username), + CONSTRAINT min_username_length CHECK (CHARACTER_LENGTH(username) >=4) +); +INSERT INTO users (username) VALUES ('a'); +SELECT * FROM users; +``` + ## 唯一约束 在 TiDB 中,默认会对唯一约束进行惰性检查。通过直到事务提交时才进行批量检查,TiDB 能够减少网络通信开销。例如: diff --git a/sql-statements/sql-statement-create-table.md b/sql-statements/sql-statement-create-table.md index f3bd6d59bc98..f887476e6655 100644 --- a/sql-statements/sql-statement-create-table.md +++ b/sql-statements/sql-statement-create-table.md @@ -6,7 +6,7 @@ aliases: ['/docs-cn/v3.1/sql-statements/sql-statement-create-table/','/docs-cn/v # CREATE TABLE -`CREATE TABLE` 语句用于在当前所选数据库中创建新表。另可参阅单独的 `CREATE TABLE LIKE` 文档。 +`CREATE TABLE` 语句用于在当前所选数据库中创建新表,与 MySQL 中 `CREATE TABLE` 语句的行为类似。另可参阅单独的 `CREATE TABLE LIKE` 文档。 ## 语法图 @@ -54,169 +54,12 @@ aliases: ['/docs-cn/v3.1/sql-statements/sql-statement-create-table/','/docs-cn/v ![TableOptionListOpt](/media/sqlgram/TableOptionListOpt.png) -## 语法说明 - -`CREATE TABLE` 用于创建一个表。目前不支持临时表,不支持 `CHECK` 约束,不支持创建表的同时从其它表导入数据功能。在语法上也支持一些 `Partition_options`,但是并不完全,就不做列举了。 - -以下是 `CREATE TABLE` 相关的语法说明: - -{{< copyable "sql" >}} - -```sql -CREATE TABLE [IF NOT EXISTS] tbl_name - (create_definition,...) - [table_options] -``` - -使用 `IF NOT EXIST` 时,即使创建的表已经存在,也不会报错,如果不指定时,则报错。 - -{{< copyable "sql" >}} - -```sql -CREATE TABLE [IF NOT EXISTS] tbl_name - { LIKE old_tbl_name | (LIKE old_tbl_name) } -``` - -使用 `LIKE` 基于一个表的定义创建一个空表,包括这个表中的列属性和索引属性。 - -```sql -create_definition: - col_name column_definition - | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...) - [index_option] ... - | {INDEX|KEY} [index_name] [index_type] (index_col_name,...) - [index_option] ... - | [CONSTRAINT [symbol]] UNIQUE [INDEX|KEY] - [index_name] [index_type] (index_col_name,...) - [index_option] ... - | {FULLTEXT} [INDEX|KEY] [index_name] (index_col_name,...) - [index_option] ... - | [CONSTRAINT [symbol]] FOREIGN KEY - [index_name] (index_col_name,...) reference_definition -``` - -`create_definition` 中 `FULLTEXT` 和 `FOREIGN KEY` 目前只是语法上支持。 - -```sql -column_definition: - data_type [NOT NULL | NULL] [DEFAULT default_value] - [AUTO_INCREMENT | AUTO_RANDOM [(length)]] - [UNIQUE [KEY] | [PRIMARY] KEY] - [COMMENT 'string'] - [reference_definition] - | data_type [GENERATED ALWAYS] AS (expression) - [VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment] - [NOT NULL | NULL] [[PRIMARY] KEY] - -data_type: - BIT[(length)] - | TINYINT[(length)] [UNSIGNED] [ZEROFILL] - | SMALLINT[(length)] [UNSIGNED] [ZEROFILL] - | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL] - | INT[(length)] [UNSIGNED] [ZEROFILL] - | INTEGER[(length)] [UNSIGNED] [ZEROFILL] - | BIGINT[(length)] [UNSIGNED] [ZEROFILL] - | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL] - | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL] - | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL] - | DECIMAL[(length[,decimals])] [UNSIGNED] [ZEROFILL] - | NUMERIC[(length[,decimals])] [UNSIGNED] [ZEROFILL] - | DATE - | TIME[(fsp)] - | TIMESTAMP[(fsp)] - | DATETIME[(fsp)] - | YEAR - | CHAR[(length)] [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | VARCHAR(length) [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | BINARY[(length)] - | VARBINARY(length) - | TINYBLOB - | BLOB - | MEDIUMBLOB - | LONGBLOB - | TINYTEXT [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | TEXT [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | MEDIUMTEXT [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | LONGTEXT [BINARY] - [CHARACTER SET charset_name] [COLLATE collation_name] - | ENUM(value1,value2,value3,...) - [CHARACTER SET charset_name] [COLLATE collation_name] - | SET(value1,value2,value3,...) - [CHARACTER SET charset_name] [COLLATE collation_name] - | JSON -``` - -`data_type` 请参考[数据类型](/data-type-overview.md)章节。 - -```sql -index_col_name: - col_name [(length)] [ASC | DESC] -``` - -`index_col_name` 中 `[ASC | DESC]` 目前只是语法上支持。 - -```sql -index_type: - USING {BTREE | HASH} -``` - -`index_type` 目前只是语法上支持。 - -```sql -index_option: - KEY_BLOCK_SIZE [=] value - | index_type - | COMMENT 'string' -``` - -`index_option` 中 `KEY_BLOCK_SIZE` 目前只是语法上支持。 - -```sql -reference_definition: - REFERENCES tbl_name (index_col_name,...) - [MATCH FULL | MATCH PARTIAL | MATCH SIMPLE] - [ON DELETE reference_option] - [ON UPDATE reference_option] - -reference_option: - RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT -``` - -```sql -table_options: - table_option [[,] table_option] ... - -table_option: - AUTO_INCREMENT [=] value - | AVG_ROW_LENGTH [=] value - | SHARD_ROW_ID_BITS [=] value - | PRE_SPLIT_REGIONS [=] value - | [DEFAULT] CHARACTER SET [=] charset_name - | CHECKSUM [=] {0 | 1} - | [DEFAULT] COLLATE [=] collation_name - | COMMENT [=] 'string' - | COMPRESSION [=] {'ZLIB'|'LZ4'|'NONE'} - | CONNECTION [=] 'connect_string' - | DELAY_KEY_WRITE [=] {0 | 1} - | ENGINE [=] engine_name - | KEY_BLOCK_SIZE [=] value - | MAX_ROWS [=] value - | MIN_ROWS [=] value - | ROW_FORMAT [=] {DEFAULT|DYNAMIC|FIXED|COMPRESSED|REDUNDANT|COMPACT} - | STATS_PERSISTENT [=] {DEFAULT|0|1} -``` - -`table_option` 目前支持的只有 `AUTO_INCREMENT`、`SHARD_ROW_ID_BITS`(详情介绍请参考 [TiDB 专用系统变量和语法](/tidb-specific-system-variables.md#shard_row_id_bits))、`PRE_SPLIT_REGIONS`、`CHARACTER SET`、`COLLATE` 和 `COMMENT`,其它只是语法上支持。具体内容参考下表,各个子句之间用逗号隔开。 +TiDB 支持以下 `table_option`。TiDB 会解析并忽略其他 `table_option` 参数,例如 `AVG_ROW_LENGTH`、`CHECKSUM`、`COMPRESSION`、`CONNECTION`、`DELAY_KEY_WRITE`、`ENGINE`、`KEY_BLOCK_SIZE`、`MAX_ROWS`、`MIN_ROWS`、`ROW_FORMAT` 和 `STATS_PERSISTENT`。 | 参数 |含义 |举例 | |----------------|--------------------------------------|----------------------------| |`AUTO_INCREMENT`|自增字段初始值 |`AUTO_INCREMENT` = 5| -|`SHARD_ROW_ID_BITS`|用来设置隐式 _tidb_rowid 的分片数量的 bit 位数 |`SHARD_ROW_ID_BITS` = 4| +| `SHARD_ROW_ID_BITS` |用来设置隐式 _tidb_rowid 的分片数量的 bit 位数 |`SHARD_ROW_ID_BITS` = 4| |`PRE_SPLIT_REGIONS`|用来在建表时预先均匀切分 `2^(PRE_SPLIT_REGIONS)` 个 Region |`PRE_SPLIT_REGIONS` = 4| |`CHARACTER SET` |指定该表所使用的字符集 | `CHARACTER SET` = 'utf8mb4'| |`COLLATE` |指定该表所使用的字符集排序规则 | `COLLATE` = 'utf8mb4_bin'| @@ -226,64 +69,82 @@ table_option: ## 示例 +创建一张简单表并插入一行数据: + {{< copyable "sql" >}} ```sql CREATE TABLE t1 (a int); +DESC t1; +SHOW CREATE TABLE t1\G +INSERT INTO t1 (a) VALUES (1); +SELECT * FROM t1; ``` -``` -Query OK, 0 rows affected (0.11 sec) -``` - -{{< copyable "sql" >}} - ```sql -CREATE TABLE t2 LIKE t1; -``` +mysql> drop table if exists t1; +Query OK, 0 rows affected (0.23 sec) -``` -Query OK, 0 rows affected (0.10 sec) -``` +mysql> CREATE TABLE t1 (a int); +Query OK, 0 rows affected (0.09 sec) -{{< copyable "sql" >}} - -```sql -DESC t1; -``` - -``` +mysql> DESC t1; +-------+---------+------+------+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+---------+------+------+---------+-------+ | a | int(11) | YES | | NULL | | +-------+---------+------+------+---------+-------+ 1 row in set (0.00 sec) -``` -{{< copyable "sql" >}} +mysql> SHOW CREATE TABLE t1\G +*************************** 1. row *************************** + Table: t1 +Create Table: CREATE TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin +1 row in set (0.00 sec) -```sql -INSERT INTO t1 VALUES (1); -``` +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) ``` -Query OK, 1 row affected (0.02 sec) -``` + +删除一张表。如果该表不存在,就建一张表: {{< copyable "sql" >}} ```sql -SELECT * FROM t1; +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; ``` -``` -+------+ -| a | -+------+ -| 1 | -+------+ -1 row in set (0.00 sec) +```sql +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(20) | NO | PRI | NULL | auto_increment | +| b | varchar(200) | NO | | NULL | | ++-------+--------------+------+------+---------+----------------+ +2 rows in set (0.00 sec) ``` ## MySQL 兼容性 @@ -291,14 +152,17 @@ SELECT * FROM t1; * TiDB 不支持 `CREATE TEMPORARY TABLE` 语法。 * 支持除空间类型以外的所有数据类型。 * 不支持 `FULLTEXT`,`HASH` 和 `SPATIAL` 索引。 -* `KEY_BLOCK_SIZE` 和 `ENGINE` 属性可被解析,但会被忽略。 -* `index_col_name` 属性支持 length 选项,最大长度限制为 3072 字节。此长度限制不会更改,具体取决于存储引擎和建表时使用的字符集。 -* `index_col_name` 属性支持 `ASC` 和 `DESC` 的索引排序选项。 +* 为了与 MySQL 兼容,`index_col_name` 属性支持 length 选项,最大长度默认限制为 3072 字节。此长度限制可以通过配置项 `max-index-length` 更改,具体请参阅 [TiDB 配置文件描述](/tidb-configuration-file.md#max-index-length)。 +* 为了与 MySQL 兼容,TiDB 会解析但忽略 `index_col_name` 属性的 `[ASC | DESC]` 索引排序选项。 * `COMMENT` 属性最多支持 1024 个字符,不支持 `WITH PARSER` 选项。 * TiDB 在单个表中最多支持 512 列。InnoDB 中相应的数量限制为 1017,MySQL 中的硬限制为 4096。 +* 当前仅支持 Range、Hash 和 Range Columns(单列)类型的分区表,详情参阅[分区表](/partitioned-table.md)。 +* TiDB 会解析并忽略 `CHECK` 约束,与 MySQL 5.7 相兼容。详情参阅 [`CHECK` 约束](/constraints.md#check-约束)。 +* TiDB 会解析并存储外键约束,但不会在 DML 语句中强制对外键进行约束检查。详情[外键约束](/constraints.md#外键约束)。 ## 另请参阅 +* [数据类型](/data-type-overview.md) * [DROP TABLE](/sql-statements/sql-statement-drop-table.md) * [CREATE TABLE LIKE](/sql-statements/sql-statement-create-table-like.md) * [SHOW CREATE TABLE](/sql-statements/sql-statement-show-create-table.md)