ToB企服应用市场:ToB评测及商务社交产业平台

标题: 有趣的特性:CHECK约束 [打印本页]

作者: 冬雨财经    时间: 2022-9-16 17:12
标题: 有趣的特性:CHECK约束
有趣的特性:CHECK约束

功能说明

在MySQL 8.0.16以前, CREATE TABLE允许从语法层面输入下列CHECK约束,但实际没有效果:
  1. CHECK (expr)
复制代码
在 MySQL 8.0.16,CREATE TABLE添加了针对所有存储引擎的表和列的CHECK约束的核心特性。CREATE TABLE允许如下针对表或列的约束语法:
  1. [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
复制代码

示例如下:
  1. CREATE TABLE t1
  2. (
  3.   CHECK (c1 <> c2),
  4.   c1 INT CHECK (c1 > 10),
  5.   c2 INT CONSTRAINT c2_positive CHECK (c2 > 0),
  6.   c3 INT CHECK (c3 < 100),
  7.   CONSTRAINT c1_nonzero CHECK (c1 <> 0),
  8.   CHECK (c1 > c3)
  9. );
复制代码
以上示例包含了列约束和表约束,命名和未命名的格式:
如果想查看上述命令所生成的约束名,可以输入以下SHOW CREATE TABLE命令:
  1. mysql> SHOW CREATE TABLE t1\G
  2. *************************** 1. row ***************************
  3.        Table: t1
  4. Create Table: CREATE TABLE `t1` (
  5.   `c1` int(11) DEFAULT NULL,
  6.   `c2` int(11) DEFAULT NULL,
  7.   `c3` int(11) DEFAULT NULL,
  8.   CONSTRAINT `c1_nonzero` CHECK ((`c1` <> 0)),
  9.   CONSTRAINT `c2_positive` CHECK ((`c2` > 0)),
  10.   CONSTRAINT `t1_chk_1` CHECK ((`c1` <> `c2`)),
  11.   CONSTRAINT `t1_chk_2` CHECK ((`c1` > 10)),
  12.   CONSTRAINT `t1_chk_3` CHECK ((`c3` < 100)),
  13.   CONSTRAINT `t1_chk_4` CHECK ((`c1` > `c3`))
  14. ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
复制代码
SQL规范要求:所有约束(包括:PRIMARY KEY, UNIQUE,FOREIGN KEY, CHECK)属于同一个命名空间(NAMESPACE),在MySQL实现中,所有的约束类型在每个schema (database)内有自己的命名空间。所以,CHECK约束的名称在SCHEMA内必须唯一,也就是说不允许有两张表使用同一个CHECK约束名称。(例外:一个临时表可能使用与非临时表一样的约束名称)
CHECK的条件表达式必须遵守以下规则,如果包含不允许的结构,将会触发错误:
约束表达式在不同的SQL模式下,可能返回不同的结果
另外,在INFORMATION_SCHEMA的CHECK_CONSTRAINTS表中存放着所有表中定义的CHECK约束的信息。
建议使用CHECK约束的场景

复杂业务场景下的约束,从架构角度看,允许有不同的实现方式:
一般性的,选择不同方式的原则如下:
  1. CREATE TABLE Departments (
  2.     ID int NOT NULL,
  3.     PID int NOT NULL,
  4.     Name varchar(255) NOT NULL Default '',
  5.     CHECK (ID>=1)
  6. );
  7. -- add check separately
  8. ALTER TABLE Departments
  9. ADD CONSTRAINT CHK_PID CHECK (ID>=1 AND PID >=0);
  10. -- remove check
  11. ALTER TABLE Departments
  12. DROP CHECK CHK_PID;
复制代码
  1. CREATE TABLE IF NOT EXISTS `department` (
  2.   `id` int NOT NULL AUTO_INCREMENT,
  3.   `pid` int COMMENT 'parent id',
  4.   `name` varchar(100) NOT NULL,
  5.   PRIMARY KEY (`id`)
  6.   ) ENGINE = InnoDB;
  7. CREATE TRIGGER pid_insert_check
  8. BEFORE INSERT ON department
  9. FOR EACH ROW
  10. BEGIN
  11.   IF (NEW.pid <> 0 AND NEW.pid NOT IN (select id from department)) THEN
  12.     signal sqlstate '45000'
  13.     set message_text = 'department parent id has to be chosen from id';
  14.   END IF;
  15. END
  16. CREATE TRIGGER pid_delete_check
  17. BEFORE DELETE ON department
  18. FOR EACH ROW
  19. BEGIN
  20.   IF (OLD.id < 0 OR OLD.id IN (select pid from department)) THEN
  21.     signal sqlstate '45000'
  22.     set message_text = 'department parent id has to be chosen from id';
  23.   END IF;
  24. END
复制代码

Enjoy GreatSQL
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4