MySQL视图详解
每博一文案
白马啸西风里写道“江南有杨柳,桃花有燕子”金鱼,汉人中,
有的是英俊勇武的少年,但这个美丽的姑娘就像古高昌国人那样固执,
那都是很好很好的,可是我偏不喜欢,谁都想被人这样义无反顾的选择吧,
不是畏首畏尾,不是瞻前顾后,更不是权衡利弊后的盛世,而是下意识的惦记和牵挂,是义无反顾的选择。
这个世界上,没有义务对你好,所以你更应该这样相信,那些冷漠和刻薄是理所当然,
那些温柔相待更应该珍惜,如果总是相信下一个会更好,那么往往遇见的会一个比一个糟糕,
经历了越多,人就越是容易拿来对比,也就越来越不相信真心,
所以,不要因为一件东西好,你才千方百计去拥有它,而是因为你已经拥有了它,才一心一意的觉得它最好
听过这样一句话,你若不懂得珍惜,我又何必去牵挂,人与人之间的关系是流动的,时间总会拆穿一些秘而不宣的事实,那就是没有人会一直在原地等你
攒够失望的人,自然会放手,一颗心就像茶炉中的开水,需要不断加火升温才滚烫,
你若对我认真,我就还你情深,你若对我沉默,我就对你冷漠
我知道,我不是最好的那一个,却也是谁也代替不了的,人与人相遇一场,何其有幸,愿你珍惜
—————— 一禅心灵庙语
文章目录
1. 视图
关于视图的内容涉及到一些有关,表SELECT
查询的内容,如有不太了解的,朋友可以移步先看看这个🔜🔜🔜 SQL 基本的 SELECT 的语法_ChinaRainbowSea的博客-CSDN博客
有助于更好的理解,我们的视图。
对于已经了解查询的盆友则可以跳过了。享受后面的视觉盛宴。
1.1 常见的数据库对象
对象 | 描述 |
---|---|
表(TABLE) | 表是存储数据的逻辑单元,以行和列的形式存在,列就是字段,行就是记录 |
数据字典 | 就是系统表,存放数据库相关信息的表,系统表的数据通常由数据库系统维护,程序员通常不应该修改,只可查看 |
约束(CONSTRAINT) | 执行数据校验的规则,用于保证数据完整性的规则 |
视图(VIEW) | 一个或者多个数据表里的数据的逻辑显示,视图并不存储数据 |
索引(INDEX) | 用于提高查询性能,相当于书的目录 |
存储过程(PROCEDURE) | 用于完成一个完整的业务处理,没有返回值,但可通过传出参数将多个值传给调用环境 |
存储过程(FUNCTION) | 用于完成一次特定的计算,具有一个返回值 |
触发器(TRIGGER) | 相当于一个事件监听器,当数据库发生特定事件后,触发器被触发,完成相应的处理 |
1.2 视图的概念
为什么我们需要视图 ???
视图一方面可以帮助我们使用表的一部分而不是所有的表,另一方面也可以针对不同的用户制定不同的查询视图的权限。
比如:针对一个公司的销售人员,我们只想给他看部分数据,而某些特殊的数据,比如:采购的价格,则不会提供给他看到。再比如:人员薪酬是个敏感的字段,那么只给某个级别以上的人员开放,其他人的查询视图中则不提供这个字段。刚才讲的只是视图的一个使用场景,实际上视图还有许多的作用,最后,我们再做总结其视图的优点和缺点。
1.3 视图的理解
视图是一种 虚拟表
,虚拟就在于:视图本身是不具有实际的存储数据的,占用很少的内存空间,它是 SQL
中的一个重要的概念。
视图的本质: 就可以看做是存储起来的 SELECT
(查询的结果) ,将 select 查询到的结果存储成一个表,方便,用于后面的查看 。再说明白点就是:将 SELECT
的结果像表一样保留下来的虚表
就是视图
。注意一点:就是视图并不会把基表(数据表)中的约束全部保留下来,而是其中的一小部分 比如:not null 非空约束可能会被视图保留下来,而 PRIMARY KEY
主键约束可能视图不会保留下来。
视图建立是在,已有表的基础上的 ,视图所(依托)的这些已有的表称为基表
。
视图的创建
和删除
只会影响到视图本身,不会影响到其依托的基表
。在数据库中,视图不会保存数据,其数据真正保持在**(基表)数据表中。 但是,当对视图中的数据进行 增加,删除和修改 操作时,基表
(数据表)** 中的数据会相应地发生变化,反之亦然,(基表
中的数据进行了 增加,删除和修改 操作时,视图 中的数据相应地也会发生变化)。
视图,是向用户提供基表数据的一种表现形式
。通常情况下,小型项目 的数据库可以不使用视图,但是在 大型项目 中,以及数据表比较复杂的情况下,视图的价值就凸显出来了,它可以帮助我们把经常查询的结果集放到虚拟表中,提升使用效率。理解和使用起来都非常方便。
1.4 视图的用途
视图虽然看起来像表,但它没有实体存储,只是一种信息。视图的便利一处在于,用户可以按照自己想要的条件收集某个表中某列的数据。
之前那种通过设置条件从表中提取记录的做法非常麻烦。如果相同的提取操作,以视图的方式执行,就可以将视图作为符合用户个人喜好的表来使用。
从用户的角度来看,视图和表在使用上并没有什么区别。和表一样,视图也可以进行 SELECT
和 UPDATE
。如果更新视图的记录,基表的记录也会更新。
另外,对于一些不能被修改的重要数据,我们可以只让管理员等具有特殊权限的人来操作相关的表。同时再准备一个收集了无关紧要部分的视图,这样就很安全了。
此外,数据库高级用户可以为初学者创建容易理解的视图来代替不易理解的表,这也是视图的用途之一。
2. 创建视图
在 CREATE VIEW 语句中嵌入子查询 ,创建数据库,创建表,创建视图,创建存储过程,创建存储函数 都是使用CREATE
中含有的子语句。
格式如下:
CREATE [OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 视图名称 [(字段列表)]
AS 查询语句
[WITH [CASCADED|LOCAL] CHECK OPTION]
简化版的创建视图
格式如下:该方式如果视图已经存在的,就无法再创建了,报错。
CREATE VIEW 视图名
AS
SELECT 有关的查询;
或是使用:OR REPLACE
如果所创建的视图不存在,就创建;反正,所创建的视图已经存在了,就会将原本的视图的内容覆盖掉,创建一个新的,不会报错,但会给予警告。
CREATE OR REPLACE VIEW 视图名
AS
SELECT 有关的查询;
创建的视图,根据查询select
中所依托的表大致可以分为以下三种
- 基于单表查询创建的视图
- 基于多表查询创建的视图
- 基于视图查询创建的视图
查询视图的方式和查询表的方式是一样的
使用 SELECT
具体格式如下
SELECT 视图中的字段名1, 视图中的字段名2,视图中的字段名3
FROM 视图;
或者查看视图中所有的内容
SELECT *
FROM 视图;
2.1 基于单表查询创建视图
基于单个表查询的结果创建视图:如下
**举例: **创建一个 查询 emps 表中 department_id = 80的 employee_id ,last_name, salary 的视图,视图名为 empvu
CREATE VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM emps
WHERE department_id = 80;
查看视图内容
SELECT *
FROM empvu80;
实际上就是我们在 SQL 查询语句的基础上封装了视图 VIEW
,这样就会基于 SQL 语句的结果集,形成一张虚拟表。
再查看该视图 empvu80下的约束
DESC empvu80; -- 查看该视图的结构
对比其依托的基表 emps 的约束
可以看到其中 employee_id 中的 主键约束,并没有被保留下来,而其中的 not null 非空约束却被保留了下来。
2.1.1 视图的字段名的设定
我们创建了一个视图的同时是,可以在视图名后面指定其字段的名称的:
注意:视图列表中的字段名设定,要于下面 select 查询的字段一一对应上,不然可能会错位
格式如下:
CREATE VIEW 视图名( 设定视图中第一列的字段名1,设定视图中第二列的字段名2 )
AS
SELECT 有关的查询;
举例: 将 emps 表中 salary > 8000 中的 employee_id, last_name, salary 改为 id, lname, sal,视图名为 vu_emp1
CREATE VIEW vu_emp1 (id,lname,sal)
AS
SELECT employee_id, last_name, salary
FROM emps
WHERE salary > 8000;
SELECT *
FROM vu_emp1;
如果我们没有在视图名后面指定字段名称,则视图中的字段列表默认和 SELECT
语句中的字段列表一致。
如果SELECT
语句中给字段取了别名,那么视图中的字段名和别名相同
举例: 将 emps 表中 salary < 8000 中的 employee_id, last_name, salary 改为 id2, lname2, sal2,视图名为 vu_emp2
CREATE VIEW vu_emp2
AS
SELECT employee_id AS id2, last_name AS lname2,salary AS sal2
FROM emps
WHERE salary < 8000;
SELECT *
FROM vu_emp2;
2.2 基于多表查询创建视图
基于多表连接查询的结果创建视图。
对于多表连接查询,想要更多了解的可以移步到 🔜🔜🔜 明了的 —— Mysql 多表连接查询_ChinaRainbowSea的博客-CSDN博客
**举例: ** 将表 emps 表中的字段 employee_id ,department_id, 以及 dapt表中的department_name查询结果创建一个是视图名为 vu_emp_dapt
CREATE VIEW vu_emps_dapt
AS
SELECT e.employee_id, e.department_id, d.department_name
FROM emps e
JOIN dapt d
ON d.department_id = e.department_id;
SELECT *
FROM vu_emps_dapt;
利用视图对数据进行格式化
我们经常需要输出某个格式的内容,比如我们想输出员工姓名和对应的部门名,对应格式为
员工名(对应的部门名),就可以使用视图来完成数据格式化的操作,这里我们需要使用上 concat
字符串拼接符。
具体实现如下
CREATE VIEW vu_emp_dept2
AS
SELECT CONCAT(e.last_name,'(',d.department_name,')') -- concat 字符串连接符
FROM emps e
JOIN dapt d
ON d.department_id = e.department_id;
SELECT *
FROM vu_emp_dept2;
2.3 基于视图查询创建视图
当我们创建好一张视图之后,还可以在它的基础上继续创建视图。
举例: 将前面我们所创建的视图 vu_emp1
查询其字段 id,lname的结果创建一个视图名为 vu_emp5
CREATE VIEW vu_emp5
AS
SELECT id,lname
FROM vu_emp1;
SELECT *
FROM vu_emp5;
3. 查看视图
- 语法1:查看数据库的表对象、视图对象。
SHOW TABLES;
-- 查看当前数据库下所有的表以及视图
- 查看视图结构,注意: 其中视图中所显示的字段的结构,是和基表中字段的结构是一样的 。格式如下:
DESC / DESCRIBE 视图名称;
DESC vu_emp5;
- 查看视图的属性信息 查看视图信息(显示数据表的存储引擎,版本,数据行数和数据大小等) ,格式如下:
SHOW TABLE STATUS LIKE '视图名称'; -- like 所以可以使用模糊查询
举例: 查看视图 vu_emp5 的信息,这是在 SQLyog 中执行查看的,可能不太美观。
SHOW TABLE STATUS LIKE 'vu_emp5'; --
打开可以在 DOS
命令中在最后面附加上 \G
,分行显示。
格式如下:
shOW TABLE STATUS LIKE '视图名称'\G -- like 所以可以使用模糊查询
执行结果显示: 注释Comment 为 VIEW ,说明该表为视图,其他的信息为 NULL,说明这是一个虚表。
- 查看视图的详细定义信息,格式如下
SHOW CREATE VIEW 视图名称;
举例: 查看视图 vu_emp5 的详细定义信息
SHOW CREATE VIEW vu_emp5;
4. 更新视图中的数据、
MySQL支持使用 INSERT,UPDATE 和 DELETE
语句对视图中的数据进行 插入,更新和删除 操作。当视图中的数据发生变化时,数据表中的数据也会发生变化,反之亦然。对基表(数据表)中的数据进行 插入,更新和删除 操作。当基表(数据表)中的数据会发生变化时,视图中的数据也会发生变化。
视图中的数据的插入,更新和删除操作和操作数据表的语法是一样的 ,表的增删改 的详细内容,大家可以移步到 : 🔜🔜🔜 Mysql: 表中数据的增删改_ChinaRainbowSea的博客-CSDN博客
下面我们使用如下 vu_emp2 视图做演示
UPDATE
更新视图某个字段的数据内容的格式如下
UPDATE 视图名
SET 视图的字段名 = 你需要更新的内容
WHERE 使用条件筛选出你需要的更新的对象(字段\列);
举例: 将视图 vu_emp1 中 id 为 103 中的 sal 改为 10000
UPDATE vu_emp1
SET sal = 10000
WHERE id = 103;
所依托的基表上的 103 的 工资也被修改了
SELECT *
FROM emps;
DELETE
删除视图某个字段下的数据内容的格式如下
DELETE FROM 视图名
WHERE 筛选找到你要删除的字段名中的数据;
举例: 将视图 vu_emp1 中 id为 114 中字段的内容删除
DELETE FROM vu_emp1
WHERE id = 114;
依托的基表emps 中的 114 也被删除了
SELECT *
FROM emps;
VALUES
视图中添加数据信息
INSERT INTO 视图名(视图字段名1,视图字段名2)
VALUES (插入的数据1,插入的数据2);
举例: 将 id 为 999, lname 为 张三, sal 为 9999的记录 添加到视图 vu_emp1中
INSERT INTO vu_emp1(id,lname,sal)
VALUES (999,'张三',9999);
结果失败,原因是:已知我们的 vu_emp1 中视图中的字段只有 id,lname,sal 于它所依托的基表 emps 上的 employee_id, last_name, salary 对应,所以视图中插入的数据只有这三个 字段的数据,可我们的基表 emps 中含有其他许多字段,没有值的插入的话默认为 NULL,但是有些字段存在约束存在一些冲突,如 not null 非空约束就,这一条就导致了,这段数据插入失败了。
4.2 不可更新的视图
要使视图可更新,视图中的行和底层基本表中的行之间必须存在 一对一
的关系。另外当视图定义出现如下情况时,视图不支持更新操作:
- 在定义视图的时候指定了
ALGORITHM = TEMPTABLE
,视图将不支持INSERT
插入和DELETE
删除操作 - 视图中不包含 基表中所有被定义为
非空又未指定默认值的列
,视图将不支持INSERT
插入操作。
因为当视图所插入的字段没有全部包含到基表的所有字段,基表中没有被插入的数据 默认为 NULL,于 not null 非空约束冲突了
- 在定义视图的
SELECT
语句中使用了JOIN
多表连接查询,视图将不支持INSERT
和DELETE
操作
因为1. 同样一样的问题,多个基表中,没有插入的数值默认是 null,于 not null 非空约束冲突了。删除也是一个道理,有的存在not null 非空约束,不可以删除归为 null.
- 在定义视图的
SELECT
语句后的字段列表中使用了,数学表达式 或子查询,视图将不支持INSERT
,也不支持UPDATE
使用数学表达式,子查询的字段值。
因为:子查询和上述的道理是一样的。而 数据表达式的查询结果,就没有实质的基表存储,没有实质的存储的基表又如何保存其的修改结果呢。
- 在定义视图的
SELECT
语句后的字段列表中使用 DISTINCT ,聚合函数,GROUP BY,HAVING,UNION 等,视图将不支持 INSERT, UPDATE,DELETE操作
因为 聚合函数,UNION 等这些查询操作的数据并没有实质的存储,都是通过一些算法查询到了组合数据。是无法进行删除和修改的
在定义视图的
SELECT
语句中包含了子查询,而子查询中引用了FROM
后面的表,视图将不支持 INSERT, UPDATE ,DELETE;当视图的创建是基于另外一个视图所创建的,也不支持INSERT;
常量视图,也不支持INSERT, UPDATE ,DELETE;
举例:首先对 视图的创建是基于另外一个视图所创建的,也不支持INSERT, UPDATE ,DELETE; 这一条进行验证
我们在 2.3 基于视图查询创建视图 创建了一个名为 vu_emp5
的视图,进行试验
INSERT
插入失败
INSERT INTO vu_emp5(id,lname)
VALUES(999,'张三');
UPDATE
更新成功
UPDATE vu_emp5
SET id = 999
WHERE id = 146;
DELETE
删除成功了
DELETE FROM vu_emp5
WHERE id = 999;
虽然可以更新视图数据,但总的来说,视图作为
虚拟表
,主要用于方便查询
, 不建议更新视图的数据。对视图数据的更改,都是通过对实际数据表里数据的操作来完成的
5. 修改,删除视图
5.1 修改视图
方式1: 使用 CREATE OR REPLACE VIEW
子句 修改视图 ,这种方式的本质就是把,如果视图不存在,则创建,如果该视图已经存在了,就将已有的视图上的内容替换掉。不会报错,可以成功执行,但会给予警告
格式如下:
CREATE OR REPLACE VIEW 视图名
AS
SELECT 有关的查询;
举例: 将视图 empvu80 修改为 依托基表为 emps 中 salary 大于 10000 的 employee_id, last_name, salary 的字段信息。
CREATE OR REPLACE VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM emps
WHERE salary > 10000;
方式二: ALTER VIEW
使用修改视图
格式如下:
ALTER VIEW 视图名
AS
SELECT 查询语句;
举例: 将视图 empvu80 修改为 依托基表为 emps 中 salary 大于 17000 的 employee_id, last_name, salary 的字段信息。
ALTER VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM emps
WHERE salary > 17000;
5.2 删除视图
删除视图只是删除视图的定义,并不会删除基表的数据。
注意: 当基于视图a, b创建了新的视图c,如果将视图 a 或者 视图 b 删除,会导致视图 c 的查询失败。这样的视图 c 需要手动删除或修改,否则影响使用。同样视图所依赖是基表被删除了,其根据这个删除的基表创建的视图,也是无效的,同样需要手动删除或修改,都是因为没有了实际数据的存储(删除了)依赖了,无效查询
使用 DROP
删除视图
方式1: 格式如下:该方式如果视图存在,则删除,如果视图不存在,不删除,并报错
DROP VIEW 视图名;
方式2: 格式如下:该方式如果视图存在,则删除,如果视图不存在,不删除,但不会报错,而是给予警告
DROP VIEW IF EXISTS 视图名;
举例: 将视图 empvu80 删除
SHOW TABLES; -- 查看当前数据库中含有的所有表和视图
DROP VIEW IF EXISTS empvu80;
6. 总结
6.1 视图优点
- 操作简单
可以将经常使用的查询操作定义为视图,可以使开发人员不需要关心视图对应的数据表的结构,表与表之间的关联关系,也不需要关心数据表之间的 业务逻辑 和 查询条件 ,而只需要简单地操作视图即可,极大简化了,开发人员对数据库的操作。
- 减少数据冗余
视图跟实际数据表不一样,它存储的是查询语句。所以,在使用的时候,我们要通过定义视图的查询语句来获取结果集。而视图本身不存储数据 ,不占用数据存储的资源,减少了数据的冗余。
- 数据安全
MySQL将用户对数据的访问限制 在某些数据的结果集上,而这些数据的结果集可以使用视图来实现。用户不必直接查询或操作数据表。这也可以理解为视图具有 隔离性
。视图相当于在用户和实际的数据表之间加了一层虚拟表。
同时,MySQL可以根据权限将用户对数据的访问限制在某些视图上,用户不需要查询数据表,可以直接通过视图获取数据表中的信息。这在一定程度上保障了数据表中数据的安全性 。
- 适应灵活多变的需求
当业务系统的需求发生变化后,如果需要改动数据表的结构,则工作量相对较大,可以使用视图来减少改动的工作量。这种方式在实际工作中使用得比较多。
- 能够分解复杂的查询逻辑
数据库中如果存在复杂的查询逻辑,则可以将问题进行分解,创建多个视图获取数据,再将创建的多个视图结合起来,完成复杂的查询逻辑
6.2 视图不足
如果我们在实际数据表的基础上创建了视图,那么,如果实际数据表的结构变更了,我们就需要及时对相关的视图进行相应的维护。 特别是嵌套的视图(就是在视图的基础上创建视图),维护会变得比较复杂。可读性不好,容易变成系统的潜在隐患。因为: 创建视图的 SQL 查询可能会对字段重命名,也可以包含复杂的逻辑,这些都会增加维护的成本。
实际项目中,如果视图过多,会导致数据库维护成本的问题。
所以,在创建视图的时候,我们需要结合实际项目需求,综合考虑视图的 优缺点 ,这样才能正确使用视图,使系统整体达到最优。
通常情况下,小型项目的数据库可以不使用视图,但是在 大型项目 中,以及数据表比较复杂的情况下,视图的价值就凸显出来了,它可以帮助我们把经常查询的结果集放到虚拟表中,提升使用效率。理解和使用起来都非常方便 。
7. 最后:
限于自身水平,其中存在的错误,希望大家多多指教,韩信点兵——多多指教,谢谢大家,后会有期,江湖再见 !!!