首先看下面這段MySQL的操作,新建一個含有a和b的表,其中a用check約束必須大於0,然而插入了一條(-2,1,1)的數據,其中a=-2,也是成功插入的。
所以MySQL只是check,但是不強制check。
mysql> create table checkDemoTable(a int,b int,id int,primary key(id));
Query OK, 0 rows affected
mysql> alter table checkDemoTable add constraint checkDemoConstraint check(a>0);
Query OK, 0 rows affected
Records: 0 Duplicates: 0 Warnings: 0
mysql> insert into checkDemoTable values(-2,1,1);
Query OK, 1 row affected
mysql> select * from checkDemoTable;
+----+---+----+
| a | b | id |
+----+---+----+
| -2 | 1 | 1 |
+----+---+----+
1 row in set
解決這個問題有兩種辦法:
- 如果需要設置CHECK約束的字段范圍小,並且比較容易列舉全部的值,就可以考慮將該字段的類型設置為枚舉類型 enum()或集合類型set()。比如性別字段可以這樣設置,插入枚舉值以外值的操作將不被允許。
mysql> create table checkDemoTable(a enum('男','女'),b int,id int,primary key(id));
Query OK, 0 rows affected
mysql> insert into checkDemoTable values('男',1,1);
Query OK, 1 row affected
mysql> select * from checkDemoTable;
+----+---+----+
| a | b | id |
+----+---+----+
| 男 | 1 | 1 |
+----+---+----+
1 row in set
2.如果需要設置CHECK約束的字段是連續的,或者列舉全部值很困難,比如正實數或正整數,那就只能用觸發器來代替約束實現數據有效性了。下面這段代碼創建了一個叫做TestField1_BeforeInsert的約束器,它將保證新插入的數據中 a 字段的值不小於零。
DELIMITER $$
CREATE TRIGGER TestField1_BeforeInsert BEFORE INSERT ON checkDemoTable
FOR EACH ROW
BEGIN
IF NEW.a < 0 THEN
SET NEW.a = 0;
END IF;
END$$