Mysql中Check约束无效的原因以及解决方法

首先看下面这段代码:

mysql> create table ss
    -> (
    ->  no int check(no <= 4 and no >=
    -> );
Query OK, 0 rows affected (0.11 sec)
 
mysql> insert into ss values(1);
Query OK, 1 row affected (0.01 sec)
 
mysql> select * from ss;
+------+
| no   |
+------+
|    1 |
+------+
1 row in set (0.00 sec)
 
mysql> insert into ss values(5);
Query OK, 1 row affected (0.03 sec)
 
mysql> select * from ss;
+------+
| no   |
+------+
|    1 |
|    5 |
+------+
2 rows in set (0.00 sec)

很明显,CHECK语句在声明中并未起到作用,为什么呢?

原因是因为,不同于SQL,在MYSQL中,CHECK只是一段可调用但无意义的子句。MySQL会直接忽略。

CHECK子句会被分析,但是会被忽略。
请参见“CREATE TABLE语法”:接受这些子句但又忽略子句的原因是为了提高兼容性,以便更容易地从其它SQL服务器中导入代码,并运行应用程序,创建带参考数据的表。

解决这个问题有两种办法:
1.
如果需要设置CHECK约束的字段范围小,并且比较容易列举全部的值,就可以考虑将该字段的类型设置为枚举类型 enum()或集合类型set()。比如性别字段可以这样设置,插入枚举值以外值的操作将不被允许。

 1 mysql> create table checkDemoTable(a enum('男','女'),b int,id int,primary key(id));
 2 Query OK, 0 rows affected
 3 
 4 mysql> insert into checkDemoTable values('男',1,1);
 5 Query OK, 1 row affected
 6 
 7 mysql> select * from checkDemoTable;
 8 +----+---+----+
 9 | a  | b | id |
10 +----+---+----+
11 | 男 | 1 |  1 |
12 +----+---+----+
13 1 row in set

如果需要设置CHECK约束的字段范围大,且列举全部值比较困难,比如:>0的值,那就只能使用触发器来代替约束实现数据的有效性了。如下代码,可以保证a>0。

CREATE TRIGGER TestField1_BeforeInsert BEFORE INSERT ON checkDemoTable
FOR EACH ROW
BEGIN
IF NEW.a < 0 THEN
SET NEW.a = 0;
END IF;

此外,在MYSQL中,域(Domain)与断言(Assertion)也是无法使用的,原因类似于CHECK,后续将会在其他文章中提到。更多相关代码可以访问
我的GITHUB

  • 11
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

图灵的猫.

小二,给客官上酒!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值