- 关于 TiDB
- 主要概念
- 操作指南
- 快速上手
- 部署
- 配置
- 安全
- 安全传输层协议 (TLS)
- 生成自签名证书
- 监控
- 迁移
- 运维
- 扩容缩容
- 升级
- 故障诊断
- 参考手册
- SQL
- 与 MySQL 兼容性对比
- SQL 语言结构
- 数据类型
- 函数与操作符
- SQL 语句
ADD COLUMN
ADD INDEX
ADMIN
ADMIN CANCEL DDL
ADMIN CHECKSUM TABLE
ADMIN CHECK [TABLE|INDEX]
ADMIN SHOW DDL [JOBS|QUERIES]
ALTER DATABASE
ALTER TABLE
ALTER USER
ANALYZE TABLE
BEGIN
CHANGE COLUMN
COMMIT
CREATE DATABASE
CREATE INDEX
CREATE TABLE LIKE
CREATE TABLE
CREATE USER
DEALLOCATE
DELETE
DESC
DESCRIBE
DO
DROP COLUMN
DROP DATABASE
DROP INDEX
DROP TABLE
DROP USER
EXECUTE
EXPLAIN ANALYZE
EXPLAIN
FLUSH PRIVILEGES
FLUSH STATUS
FLUSH TABLES
GRANT <privileges>
INSERT
KILL [TIDB]
LOAD DATA
LOAD STATS
MODIFY COLUMN
PREPARE
RENAME INDEX
RENAME TABLE
REPLACE
REVOKE <privileges>
ROLLBACK
SELECT
SET [NAMES|CHARACTER SET]
SET PASSWORD
SET TRANSACTION
SET [GLOBAL|SESSION] <variable>
SHOW CHARACTER SET
SHOW COLLATION
SHOW [FULL] COLUMNS FROM
SHOW CREATE TABLE
SHOW DATABASES
SHOW ENGINES
SHOW ERRORS
SHOW [FULL] FIELDS FROM
SHOW GRANTS
SHOW INDEXES [FROM|IN]
SHOW INDEX [FROM|IN]
SHOW KEYS [FROM|IN]
SHOW PRIVILEGES
SHOW [FULL] PROCESSSLIST
SHOW SCHEMAS
SHOW STATUS
SHOW [FULL] TABLES
SHOW TABLE STATUS
SHOW [GLOBAL|SESSION] VARIABLES
SHOW WARNINGS
START TRANSACTION
TRACE
TRUNCATE
UPDATE
USE
- 约束
- 生成列
- 字符集
- 配置
- tidb-server
- pd-server
- tikv-server
- 安全
- 事务
- 系统数据库
- 错误码
- 支持的连接器和 API
- 垃圾回收 (GC)
- 性能调优
- 监控指标
- 报警规则
- 最佳实践
- TiSpark 使用指南
- TiDB Binlog
- 周边工具
- 常见问题 (FAQ)
- 技术支持
- 贡献
- 版本发布历史
- 术语表
你正在查看 TiDB 数据库的较旧版本 (TiDB v2.1) 的文档。
约束
TiDB 支持的约束与 MySQL 的基本相同。
非空约束
TiDB 支持的非空约束规则与 MySQL 支持的一致。例如:
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
age INT NOT NULL,
last_login TIMESTAMP
);
mysql> INSERT INTO users (id,age,last_login) VALUES (NULL,123,NOW());
Query OK, 1 row affected (0.02 sec)
mysql> INSERT INTO users (id,age,last_login) VALUES (NULL,NULL,NOW());
ERROR 1048 (23000): Column 'age' cannot be null
mysql> INSERT INTO users (id,age,last_login) VALUES (NULL,123,NULL);
Query OK, 1 row affected (0.03 sec)
第一条
INSERT
语句成功,因为对于定义为AUTO_INCREMENT
的列,允许NULL
作为其特殊值。TiDB 将为其分配下一个自动值。第二条
INSERT
语句失败,因为age
列被定义为NOT NULL
。第三条
INSERT
语句成功,因为last_login
列没有被明确地指定为NOT NULL
。默认允许NULL
值。
CHECK
约束
TiDB 会解析并忽略 CHECK
约束。该行为与 MySQL 5.7 的相兼容。
示例如下:
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 能够减少网络开销、提升性能。例如:
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(60) NOT NULL,
UNIQUE KEY (username)
);
INSERT INTO users (username) VALUES ('dave'), ('sarah'), ('bill');
默认情况下 tidb_constraint_check_in_place=0
:
BEGIN;
INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill');
Query OK, 0 rows affected (0.00 sec)
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
INSERT INTO users (username) VALUES ('steve'),('elizabeth');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
COMMIT;
ERROR 1062 (23000): Duplicate entry 'bill' for key 'username'
在第二个示例中,唯一约束的检查推迟到事务提交时才进行。由于 bill
值已经存在,这一行为导致了重复键错误。
当 tidb_constraint_check_in_place
的值设置为 1
时,则会在执行语句时就对唯一约束进行检查。例如:
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(60) NOT NULL,
UNIQUE KEY (username)
);
INSERT INTO users (username) VALUES ('dave'), ('sarah'), ('bill');
SET tidb_constraint_check_in_place = 1;
Query OK, 0 rows affected (0.00 sec)
BEGIN;
Query OK, 0 rows affected (0.00 sec)
INSERT INTO users (username) VALUES ('jane'), ('chris'), ('bill');
ERROR 1062 (23000): Duplicate entry 'bill' for key 'username'
..
第一条 INSERT
语句导致了重复键错误。这会造成额外的网络通信开销,并可能降低插入操作的吞吐量。
主键约束
与 MySQL 行为一样,主键约束包含了唯一约束,即创建了主键约束相当于拥有了唯一约束。此外,TiDB 其他的主键约束规则也与 MySQL 相似。例如:
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
Query OK, 0 rows affected (0.12 sec)
CREATE TABLE t2 (a INT NULL PRIMARY KEY);
ERROR 1171 (42000): All parts of a PRIMARY KEY must be NOT NULL; if you need NULL in a key, use UNIQUE instead
CREATE TABLE t3 (a INT NOT NULL PRIMARY KEY, b INT NOT NULL PRIMARY KEY);
ERROR 1068 (42000): Multiple primary key defined
CREATE TABLE t4 (a INT NOT NULL, b INT NOT NULL, PRIMARY KEY (a,b));
Query OK, 0 rows affected (0.10 sec)
分析:
- 表
t2
创建失败,因为定义为主键的列a
不能允许NULL
值。 - 表
t3
创建失败,因为一张表只能有一个主键。 - 表
t4
创建成功,因为虽然只能有一个主键,但 TiDB 支持定义一个多列组合作为复合主键。
除上述规则外,默认情况下,TiDB 还有一个额外限制,即一旦一张表创建成功,其主键就不能再改变。如果需要添加/删除主键,需要在 TiDB 配置文件中将 alter-primary-key
设置为 true
,并重启 TiDB 实例使之生效。
当开启添加/删除主键功能以后,TiDB 允许对表添加/删除主键。但需要注意的是,如果开启该功能前所创建表带有整数类型的主键,即使开启添加/删除主键功能,也不能删除其主键约束。
外键约束
TiDB 仅部分支持外键约束功能。
TiDB 支持创建外键约束。例如:
CREATE TABLE users (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
doc JSON
);
CREATE TABLE orders (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL,
doc JSON,
FOREIGN KEY fk_user_id (user_id) REFERENCES users(id)
);
SELECT table_name, column_name, constraint_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage WHERE table_name IN ('users', 'orders');
+------------+-------------+-----------------+-----------------------+------------------------+
| table_name | column_name | constraint_name | referenced_table_name | referenced_column_name |
+------------+-------------+-----------------+-----------------------+------------------------+
| users | id | PRIMARY | NULL | NULL |
| orders | id | PRIMARY | NULL | NULL |
| orders | user_id | fk_user_id | users | id |
+------------+-------------+-----------------+-----------------------+------------------------+
3 rows in set (0.00 sec)
TiDB 也支持使用 ALTER TABLE
命令来删除外键(DROP FOREIGN KEY
)和添加外键(ADD FOREIGN KEY
):
ALTER TABLE orders DROP FOREIGN KEY fk_user_id;
ALTER TABLE orders ADD FOREIGN KEY fk_user_id (user_id) REFERENCES users(id);
注意
TiDB 支持外键是为了在将其他数据库的数据迁移到 TiDB 时,避免该语法导致的报错。但是,TiDB 不会在 DML 语句中对外键进行约束检查。例如,即使
users
表中不存在id=123
的记录,下列事务也能提交成功:START TRANSACTION; INSERT INTO orders (user_id, doc) VALUES (123, NULL); COMMIT;