简介
视图(
View
)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
通俗的讲,视图只保存了查询的
SQL
逻辑,不保存查询结果。所以我们在创建视图的时候,主要的工作就落在创建这条SQL
查询语句上。
语法
-- 创建视图
create or replace view stu_v_1 as select id,name from student where id <= 10;
-- 查询视图
show create view stu_v_1;
select * from stu_v_1; select * from stu_v_1 where id < 3;
-- 修改视图
create or replace view stu_v_1 as select id,name,no from student where id <= 10;
alter view stu_v_1 as select id,name from student where id <= 10;
-- 删除视图
drop view if exists stu_v_1;
插入
-- 创建或者修改一个视图
create or replace view stu_v_1 as select id,name from student where id <= 10 ;
-- 查询视图
select * from stu_v_1;
-- 插入视图 因为视图没有真实数据,只是一个查询语句,所以insert插入的是 student原始表
insert into stu_v_1 values(6,'Tom');
-- 虽然视图的查询条件是id <= 10, 并且视图没有检查条件,所以依然可以插入student表,只是
-- 查询视图是看不到id=17的这条记录的
insert into stu_v_1 values(17,'Tom22');
执行上述的
SQL
,我们会发现,
id
为
6
和
17
的数据都是可以成功插入的。 但是我们执行查询,查询出 来的数据,却没有id
为
17
的记录。
因为我们在创建视图的时候,指定的条件为
id<=10, id
为
17
的数据,是不符合条件的,所以没有查
询出来,但是这条数据确实是已经成功的插入到了基表中。
如果我们定义视图时,如果指定了条件,然后我们在插入、修改、删除数据时,是否可以做到必须满足 条件才能操作,否则不能够操作呢? 答案是可以的,这就需要借助于视图的检查选项了。
检查 WITH CHECK OPTION
当使用WITH CHECK OPTION子句创建视图时,MySQL会通过视图检查正在更改的每个行,例如 插 入,更新,删除,以使其符合视图的定义。 MySQL允许基于另一个视图创建视图,它还会检查依赖视 图中的规则以保持一致性。为了确定检查的范围,mysql提供了两个选项: CASCADED 和 LOCAL ,默认值为 CASCADED 。
CASCADED 级联
如果存在以上3个视图,因为v2带了级联检查,导致虽然v1创建时没有级联检查,也会被动给赋予级联检查。
insert into v3 values(13, 'Tom');
insert into v3 values(17, 'Tom');
insert into v3 values(28, 'Tom');
插入id = 13 时,插入成功。v3没有检查条件,13 满足 v2的级联插件,以及v1的被动级联检查。
插入id = 17,是,插入成功,v3没有检查条件,虽然大于15,但只是v3查询不到依然可以通过v3, 并且满足v2,v1的级联检查条件。
插入 id = 28 时,插入失败,v3没有检查条件,虽然大于15,但只是v3查询不到依然可以通过v2的,但是v1的检查失败所以插入失败。
LOCAL
比如,v2视图是基于v1视图的,如果在v2视图创建的时候指定了检查选项为 local ,但是v1视图创 建时未指定检查选项。 则在执行检查时,知会检查v2,不会检查v2的关联视图v1。
插入v3时,没有设置检查,无论id为多少都是通过,v2带有local的检查,所以只能插入id>=10的,否则插入失败。通过了v2,v1没有检查,所有的id都可以通过。
所有local只限定自己的检查,对父查询没有任何控制效果
更新
安全
案例
create or replace view user_v1 as
select id, name, profession, age, gender, status, createtime
from tb_user;
create or replace view stu_cour_v1 as
select s.name '姓名', s.no '学号', c.name '课程' from student s , student_course sc, course c
where s.id = sc.studentid and sc.courseid = c.id;