定义
当使用 WITH CHECK OPTION 子句创建视图时,MySQL会通过视图检查正在更改的每个行,例如 插入,更新,删除,以使其符合视图的定义。
MySQL允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。为了确定检查的范围,mysql提供了两个选项:CASCADED 和 LOCAL ,默认值为 CASCADED 。
检查选项的关键字是检查,即检查操作记录的时候,是否符合视图的定义?如果符合则执行成功,不符合则执行失败。
例子
User 表
为了举例说明,我们先创建一个用户表(user),创建用户表的语句如下:
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`age` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE
)
定义视图
先定义一个不带检查选项的视图,查询年龄大于等于 18 的用户:
ALTER ALGORITHM = UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `user_age_gte_18` AS select `user`.`id` AS `id`,`user`.`name` AS `name`,`user`.`created_at` AS `created_at`,`user`.`updated_at` AS `updated_at`,`user`.`age` AS `age` from `user` where (`user`.`age` >= 18) ;
我们向 user_age_gte_18
的视图里面添加两条数据,一条年龄小于 18 的数据,一条大于 18 岁的数据:
- name: 东方,age: 17;
- name: 维德,age: 21;
向视图 user_age_gte_18
添加数据的语句:
INSERT INTO user_age_gte_18(`name`,`age`) VALUES ('东方', 17);
INSERT INTO user_age_gte_18(`name`,`age`) VALUES ('维德', 21);
可以看出,我们成功地向 user
表中添加了这两条数据,但是感觉存在矛盾:我们定义的视图 user_age_gte_18
是用于查询年龄大于等于 18 的用户,但是现在却能成功地添加 17 岁的东方。
想要避免这种情况,可以使用检查选项。
使用检查选项
语法:
CREATE [OR REPLACE] VIEW 视图名称[(列名列表)] AS SELECT语句 [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]
我们在 user_age_gte_18
视图的基础上加上检查选项,即在创建 user_age_gte_18
视图语句的末尾加上 WITH CHECK OPTION
。
MySQL
提供了两个选项:CASCADED
和 LOCAL
,默认值为 CASCADED
。如果视图是基于表创建的,这两个选项就没什么区别。而 user_age_gte_18
视图是基于 user
表创建的,所以使用 CASCADED
和 LOCAL
都是一样的,就用 CASCADED
来举例说明,它们之间的差异会起另外一篇博客来说明:
ALTER ALGORITHM = UNDEFINED DEFINER=`root`@`%` SQL SECURITY DEFINER VIEW `user_age_gte_18` AS select `user`.`id` AS `id`,`user`.`name` AS `name`,`user`.`created_at` AS `created_at`,`user`.`updated_at` AS `updated_at`,`user`.`age` AS `age` from `user` where (`user`.`age` >= 18) WITH CASCADED CHECK OPTION;
我们再向 user_age_gte_18
的视图里面添加两条数据:
- name: 艾AA,age: 15;
- name: 智子,age: 23;
向视图 user_age_gte_18
添加数据的语句:
INSERT INTO user_age_gte_18(`name`,`age`) VALUES ('艾AA', 15);
INSERT INTO user_age_gte_18(`name`,`age`) VALUES ('智子', 23);
从表中可以看出,使用了检查选项后,只有 23 岁的智子成功地添加到了 user
表中。因为艾AA的年龄小于 18 岁,所以没有被添加到 user
表中,这样就更符合 user_age_gte_18
视图的定义。