上面例子有一点说明下,
1. 约束tb_f1_r1_nonzero、tb_f1_r1r2_chk1、tb_f1_r1r3_chk 不跟随固定的列,对全局有效,也可以说基于表的 check 约束。
2. 约束tb_f1_r1_chk1 包含 约束 tb_f1_r1_nonezero, 这样 tb_f1_r1_nonezero 永远探测不到异常。所以检查后,去掉这个约束。
拿掉多余的约束后的定义,
mysql> create table f1
-> (
-> r1 int constraint tb_f1_r1_chk1 check (r1 > 10),
-> r2 int constraint tb_f1_r2_positive check (r2 > 0),
-> r3 int constraint tb_f1_r3_chk1 check (r3 < 100),
-> constraint tb_f1_r1r2_chk1 check (r1 <> r2),
-> constraint tb_f1_r1r3_chk1 check (r1 > r3)
-> );
Query OK, 0 rows affected (0.02 sec)
那针对这张表做个测试,可以看到这里每个列的约束其实是“与”的关系,任何一列约束不成立写入就失败。
mysql> insert into f1 values (20,10,10);
Query OK, 1 row affected (0.01 sec)
mysql> insert into f1 values (10,10,10);
ERROR 3819 (HY000): Check constraint 'tb_f1_r1_chk1' is violated.
mysql> insert into f1 values (20,-10,10);
ERROR 3819 (HY000): Check constraint 'tb_f1_r2_positive' is violated.
mysql> insert into f1 values (20,10,30);
ERROR 3819 (HY000): Check constraint 'tb_f1_r1r3_chk1' is violated.
那接下来我们改造刚开始那个触发器,只要把相关条件加进去就可以实现同样的 check 列约束。
DELIMITER $$
USE `ytt`$$
DROP TRIGGER /*!50032 IF EXISTS */ `tr_check_f1_r1`$$
CREATE
/*!50017 DEFINER = 'root'@'%' */
TRIGGER `tr_check_f1_r1` BEFORE INSERT ON `f1`
FOR EACH ROW BEGIN
DECLARE v1 TINYINT DEFAULT 0;
IF (new.r1 > 10 AND new.r1 > new.r3 AND new.r1 <> new.r2 AND new.r2 > 0 AND new.r3 < 100) = 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Failed to write: constraint check: \n (\n r1 >10 \n&& r1 > r3 \n&& r1 <> r2 \n&& r2> 0 \n&& r3 < 100\n).";
END IF;
END;
$$
DELIMITER ;
测试下效果,
mysql> insert into f1 values (20,30,100);
ERROR 1644 (45000): Failed to write: constraint check:
(
r1 >10
&& r1 > r3
&& r1 <> r2
&& r2> 0
&& r3 < 100
).
mysql> insert into f1 values (100,30,90);
Query OK, 1 row affected (0.01 sec)
mysql> select * from f1;
+------+------+------+
| r1 | r2 | r3 |
+------+------+------+
| 100 | 30 | 90 |
+------+------+------+
1 row in set (0.00 sec)