MySQL:视图【详解】

1、视图

1.1 视图的定义

视图是在数据库中定义的虚拟表。它是一个基于一个或多个实际表的查询结果集,可以像实际表一样被查询和操作。视图可以看作是一个动态生成的数据表,其内容是从其他表中选择、过滤和计算得到的。

视图通过使用SQL查询语句来定义,这些查询语句可以包括与一个或多个表的连接、条件过滤、列计算、聚合函数等操作。在视图定义中,我们可以指定要在视图中包含的列和行,以及对这些列进行何种计算和处理。

1.2 为什么要使用视图

视图的使用有两大因素:

1.保护敏感数据:当我们使用 select+表名 的形式执行查询操作时,查询出的数据是不受约束的,当数据中含有用户的隐私数据如:密码、地址、身份证号码时,那么使用 select+表名 的形式,这些隐私数据将暴露无遗,而视图可以有效防止隐私的暴露,隐藏关键字段,避免别有用心之人的利用。

2.降低开发成本:当开发人员需要联合多张表查询时,那么这时的查询语句将会非常的复杂,而每次查询都需要重新编写这些SQL语句,这将非常影响工作效率,那么这时数据库开发人员就可以将这些SQL语句抽象到视图中,开发人员查询时就可以通过视图进行查询。

  • 例如:查询用户的所有信息和考试成绩(四表联合查询)
-- 查询用户的所有信息和考试成绩(四表联合查询)
SELECT
 st.student_id, st.`name`, 
 cl.class_id, cl.`name`, 
 co.course_id, co.name,
 sc.score
 FROM 
 student st, class cl, score sc, course co
 WHERE 
 st.class_id = cl.class_id AND
 sc.student_id = st.student_id AND
 co.course_id = sc.course_id
 ORDER BY 
 st.student_id;

每次查询时都需要编写这样复杂的SQL语句,这是非常影响效率的,并且可以任意指定列查看隐私数据,此时我们就可以将这些语句抽象到视图中,既提高了开发效率,又保护了用户隐私。

2、 视图的创建

上文已经讲到,视图的使用可以降低开发成本,我们只需创建视图,将相关SQL语句抽象到视图中,通过视图来查询即可。

2.1 不指定列名的创建

创建视图时,我们可以不指定视图中的列名,仅仅通过AS后SQL语句的结果集中的列名来当做视图中的列。

而当我们通过视图查询时,结果如下:

为什么会出现列名重复的错误提示呢?

—— 这是由于我们在定义视图时没有指定列名,这时视图中的列是由结果集中的列决定的,而结果集中的列出现了多个重复的列‘name’,所以出现了列名重复的报错信息。

此时,我们只需将结果集中的列起上不同的别名,让这些列名不重复即可:

 -- 定义视图
 -- 不指定列名的视图的定义
 CREATE VIEW v_student_score AS (
	 SELECT
	 st.student_id, 
	 st.`name` student_name, #结果集中列名重复时要起别名
	 cl.class_id, 
	 cl.`name` class_name, 
	 co.course_id, 
	 co.`name` course_name,
	 sc.score
	 FROM 
	 student st, class cl, score sc, course co
	 WHERE 
	 st.class_id = cl.class_id AND
	 sc.student_id = st.student_id AND
	 co.course_id = sc.course_id
	 ORDER BY 
	 st.student_id
 );

创建成功后,我们可以使用 show tables; #查看视图

我们也可以通过,show create view 视图名; #查看创建视图的SQL语句

 -- 查看试图
 SHOW TABLES;
 -- 查看创建视图的SQL语句
 SHOW CREATE VIEW v_student_score;

2.2 指定列名的创建

我们也可以在创建视图时指定列名,此时有一个好处:指定列名之后,视图会根据指定的列名创建,查询结果集中是否有重复的列名并不影响。 

也就是说,此时我们不需要关注结果集中是否有重复的列名,也不需要给重复的列名起别名。

例如:(注意,本示例创建的视图并未使用order by子句) 

-- 定义视图
 -- 指定列名的视图的定义
 CREATE VIEW v_student_score_v1 (
 id, name, class_id, class_name, course_id, course_name, score
 ) AS (
	 SELECT
	 st.student_id, 
	 st.`name`,
	 cl.class_id, 
	 cl.`name`, 
	 co.course_id, 
	 co.`name`, #不需要给结果集中重复的列起别名
	 sc.score
	 FROM 
	 student st, class cl, score sc, course co
	 WHERE 
	 st.class_id = cl.class_id AND
	 sc.student_id = st.student_id AND
	 co.course_id = sc.course_id
 );

注意:上述的两种创建方式都是可以的,推荐使用第二种,即指定列名的创建


3、 视图的使用

我们可以通过封装的视图来进行查询操作:

注意,上文已经提到 视图v_student_v1 是未进行排序的视图,在查询时,我们可以给视图中的结果集指定排序规则:

 -- 使用视图
 SELECT * FROM v_student_score_v1 ;
 -- 使用视图 --> 对score进行升序排序	
 SELECT * FROM v_student_score_v1 ORDER BY score ;

4、 视图与基础表的相互影响

接下来让我们一起探索视图与基础表间数据修改之间的关系。

4.1 更新基础表数据

我们先来探索在基础表中修改的数据是否能影响到视图。

先上总结:在基本表中修改的数据会影响到视图中。

接下来让我们一步一步验证:

第一步:我们现在先来修改基础表中的数据:

第二步:使用视图查询,查看修改的数据是否影响到视图:

 综上:在基本表中修改的数据会影响到视图中。

-- 查看修改前的基础表
 SELECT * FROM score WHERE student_id = 1 AND course_id = 1;
 
 -- 更新基础表数据
 -- 将id = 1 的学生 course_id = 1 的课程成绩修改为100
 UPDATE 
 score 
 SET score = 100 
 WHERE 
 student_id = 1 AND 
 course_id = 1;
 
  -- 查看修改后的基础表的成绩
 SELECT * FROM score WHERE student_id = 1 AND course_id = 1;
 
 -- 查看视图中的数据是否收到影响
 select * FROM v_student_score_v1;

4.2 更新视图数据

4.2.1 视图是否可进行更新操作

我们先来更新 视图v_student_score,即上文创建时没有指定列名的但指定了order by排序规则的视图。

第一步:我们在v_student_score视图中将刚才修改为100的成绩修改为80,:

出现了上图的报错,提示我们:视图中如果使用了group by子句,则视图不能进行更新update操作。

OK,我们还有一个没有使用order by的视图,即:v_student_score_v1,我们继续在这个视图中进行update操作。

第二步:我们继续在v_student_score_v1视图中进行update操作。

注意:若视图指定了列名,则修改数据时,一定要使用视图中指定的列名,因为视图创建后,与基础表间已实现断藕。

发现,在该视图中成功更新了数据。

故综上:当在视图中使用order by 时,不允许在视图中进行更新update操作。

但在视图中,不仅仅是只有使用了order by语句才不允许进行更新操作,

使用了以下SQL,不允许在视图中进行update操作:

  1. 使用聚合函数
  2. 使用distinct
  3. 使用order by
  4. 使用group by以及having子句
  5. 使用union或union all
  6. 查询列表时,使用子查询
  7. 在from子句中引用不可更新的视图

4.2.2 视图更新对基础表的影响

同样,先上结论:更新视图中的数据同样会影响到基础表。

通过进行视图和基础表间数据更新的实验,得出以下结论:

  • 不论更新了视图还是基础表,都会相互影响,查询处来的数据都是最新结果。
  • 即:修改基础表会影响视图,修改视图也会影响基础表。
 -- 更新视图
 UPDATE v_student_score_v1 SET score = 80 WHERE id = 1 AND course_id = 1;
 
 -- 查看基础表数据 --> 发现基础表受影响
 SELECT * FROM score WHERE student_id = 1 and course_id = 1;

 5、视图的删除

语法:drop view 视图名;


6、视图的优点

  •  简单性:不用编写复杂的SQL,只通过使用公开对外提供的视图来查询数据。

  • 安全性:通过视图,可以隐藏表中的敏感数据。

  • 逻辑数据独立性:视图可以指定列名,所以不论底层表结构如何变化,底层列名如何变化,只需修改视图的定义即可,视图指定的列名仍然为原来的名称,这样实现了应用程序与数据库的解耦,不管应用程序改了什么内容,只认数据库的视图,不用"牵一发而动全身"。

  • 重命名列:视图允许用户重命名列名,以增强数据可读性。


END

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值