文章标题:
探秘MySQL中的视图
文章内容:

目录
一. 视图
1.1 视图的定义
1.2 视图的创建
1.3 视图数据的修改
1.4 视图的删除
1.5 视图的优势
二. 用户管理
2.1 用户的查看
2.2 新用户的创建
2.3 用户密码的更改
2.4 用户的删除
三. 权限管理
3.1 当前用户权限的查看
3.2 权限的赋予
3.3 权限的收回
一. 视图
之前我们学习了联合查询,不过联合查询的语句通常比较复杂,当我们需要多次使用相同的查询语句时,就会显得很麻烦,于是我们引入视图来对复杂的SQL语句进行封装,以此简化操作。
1.1 视图的定义
视图是由SELECT语句所定义的虚拟表,它的结构和数据来源于底层的基表,视图中存储的其实是查询语句,当用户访问视图时,数据库会执行该查询语句,从基表中提取数据并返回结果。用户可以像操作普通表一样使用视图进行查询、更新等操作。

就像上面的SQL语句是一个涉及4张表的联合查询语句,如此复杂的语句就可以用视图来封装,从而简化SQL语句~
1.2 视图的创建
创建视图的语法:
# 语法
CREATE VIEW view_name [(column_list)] AS select_statement
创建 视图关键字 视图名称 查询语句
测试数据:查询MySQL成绩比Java成绩好的同学
mysql> select distinct *from student s,score s1,score s2,course c1,course c2 where s.id=s1.student_id
-> and s.id=s2.student_id and s1.course_id=c1.id and s2.course_id=c2.id
-> and c1.name='Java' and c2.name='MySQL' and s1.sco<s2.sco;
+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+----+------+----+-------+
| id | name | sno | age | gender | class_id | sco | student_id | course_id | sco | student_id | course_id | id | name | id | name |
+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+----+------+----+-------+
| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 70.5 | 1 | 1 | 98.5 | 1 | 3 | 1 | Java | 3 | MySQL |
| 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 33 | 3 | 1 | 68 | 3 | 3 | 1 | Java | 3 | MySQL |
+----+-----------+--------+------+--------+----------+------+------------+-----------+------+------------+-----------+----+------+----+-------+
2 rows in set (0.00 sec)
像这样复杂的SQL语句,每次都要输入很多内容还得思考联合查询的逻辑,非常麻烦,所以我们用视图来包装一下:
-- 创建视图
CREATE VIEW v_Java_or_MySQL AS
SELECT DISTINCT
s.id,
s.name,
s1.sco AS java_sco, -- 给 Java 课程成绩取别名
s2.sco AS mysql_sco -- 给 MySQL 课程成绩取别名
FROM
student s,
score s1,
score s2,
course c1,
course c2
WHERE
s.id = s1.student_id
AND s.id = s2.student_id
AND s1.course_id = c1.id
AND s2.course_id = c2.id
AND c1.name = 'Java'
AND c2.name = 'MySQL'
AND s1.sco < s2.sco;
-- 查询视图
mysql> select *from v_Java_or_MySQL;
+----+-----------+----------+-----------+
| id | name | java_sco | mysql_sco |
+----+-----------+----------+-----------+
| 1 | 唐三藏 | 70.5 | 98.5 |
| 3 | 猪悟能 | 33 | 68 |
+----+-----------+----------+-----------+
2 rows in set (0.01 sec)
查询学生的姓名和总分(隐藏学号和各科成绩):
-- 直接使用真实表查询
mysql> select s.name,sum(sc.sco)from student s,score sc where s.id=sc.student_id group by s.name;
+-----------+-------------+
| name | sum(sc.sco) |
+-----------+-------------+
| 唐三藏 | 469 |
| 孙悟空 | 179.5 |
| 猪悟能 | 200 |
| 沙悟净 | 218 |
| 宋江 | 118 |
| 武松 | 178 |
| 李逹 | 172 |
+-----------+-------------+
7 rows in set (0.00 sec)
-- 但是此时还可以使用学号进行查询
mysql> select s.sno,sum(sc.sco)from student s,score sc where s.id=sc.student_id group by s.sno;
+--------+-------------+
| sno | sum(sc.sco) |
+--------+-------------+
| 100001 | 469 |
| 100002 | 179.5 |
| 100003 | 200 |
| 100004 | 218 |
| 200001 | 118 |
| 200002 | 178 |
| 200003 | 172 |
+--------+-------------+
7 rows in set (0.00 sec)
-- 使用视图
mysql> create view v_total as select s.name,sum(sc.sco)from student s,score sc where s.id=sc.student_id group by s.name;
Query OK, 0 rows affected (0.01 sec)
-- 查询视图
mysql> select name from v_total;
+-----------+
| name |
+-----------+
| 唐三藏 |
| 孙悟空 |
| 猪悟能 |
| 沙悟净 |
| 宋江 |
| 武松 |
| 李逹 |
+-----------+
7 rows in set (0.00 sec)
-- 此时就只能从视图中查询到学生名字,查询不到学生的学号了
那么以上情况如果直接使用真实表进行查询,想要查看什么信息就只需要加上需要查看的字段即可,但是假设现在是一个银行系统,如果能够这样随机查看想要查看的内容,那么就没有办法保证信息的安全性了。
视图还可以与真实表进行表连接查询:
mysql> select *from student,v_total where student.name=v_total.name;
+----+-----------+--------+------+--------+----------+-----------+-------------+
| id | name | sno | age | gender | class_id | name | sum(sc.sco) |
+----+-----------+--------+------+--------+----------+-----------+-------------+
| 1 | 唐三藏 | 100001 | 18 | 男 | 1 | 唐三藏 | 469 |
| 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 孙悟空 | 179.5 |
| 3 | 猪悟能 | 100003 | 18 | 男 | 1 | 猪悟能 | 200 |
| 4 | 沙悟净 | 100004 | 18 | 男 | 1 | 沙悟净 | 218 |
| 5 | 宋江 | 200001 | 18 | 女 | 2 | 宋江 | 118 |
| 6 | 武松 | 200002 | 18 | 男 | 2 | 武松 | 178 |
| 7 | 李逹 | 200003 | 18 | 男 | 2 | 李逹 | 172 |
+----+-----------+--------+------+--------+----------+-----------+-------------+
7 rows in set (0.00 sec)
1.3 视图数据的修改
对真实表的数据进行修改会影响视图,因为视图本质上没有保存数据,它保存的是查询语句,每次使用视图时都会执行该查询语句返回结果,所以真实表的数据不管怎么变,每次使用视图都是一次新的查询。
将孙悟空的Java成绩修改为99分:
-- 修改成绩
mysql> update score set sco=99 where student_id =(select student.id from student where name='孙悟空')
-> and course_id= (select course.id from course where name='Java');
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
-- 查看修改结果
mysql> select *from student,score,course where student.id=score.student_id and course.id=score.course_id and student.name='孙悟空' and course.name='Java';
+----+-----------+--------+------+--------+----------+------+------------+-----------+----+------+
| id | name | sno | age | gender | class_id | sco | student_id | course_id | id | name |
+----+-----------+--------+------+--------+----------+------+------------+-----------+----+------+
| 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 99 | 2 | 1 | 1 | Java |
| 2 | 孙悟空 | 100002 | 18 | 女 | 1 | 99 | 2 | 1 | 1 | Java |
+----+-----------+--------+------+--------+----------+------+------------+-----------+----+------+
2 rows in set (0.00 sec)
-- 这里查询出两条数据是因为有重复数据
不仅通过真实表修改数据会影响视图,通过视图修改数据也会影响到基表:
-- 封装该语句
mysql> select student.id,student.name,student.sno,course.name,score.sco from student,score,course where student.id=score.student_id and course.id=score.course_id and student.name='孙悟空' and course.name='Java';
+----+-----------+--------+------+------+
| id | name | sno | name | sco |
+----+-----------+--------+------+------+
| 2 | 孙悟空 | 100002 | Java | 99 |
| 2 | 孙悟空 | 100002 | Java | 99 |
+----+-----------+--------+------+------+
2 rows in set (0.00 sec)
-- 创建视图
mysql> create view v_java_sco as select student.id,student.name as'学生姓名',student.sno,course.name as '课程名称',score.sco from student,score,course where student.id=score.student_id and course.id=score.course_id and student.name='孙悟空' and course.name='Java';
Query OK, 0 rows affected (0.01 sec)
-- 查看视图
mysql> select *from v_java_sco;
+----+--------------+--------+--------------+------+
| id | 学生姓名 | sno | 课程名称 | sco |
+----+--------------+--------+--------------+------+
| 2 | 孙悟空 | 100002 | Java | 99 |
| 2 | 孙悟空 | 100002 | Java | 99 |
+----+--------------+--------+--------------+------+
2 rows in set (0.01 sec)
-- 通过视图将孙悟空的java成绩修改成60
mysql> update v_java_sco set sco=60;
Query OK, 2 rows affected (0.01 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select *from v_java_sco;
+----+--------------+--------+--------------+------+
| id | 学生姓名 | sno | 课程名称 | sco |
+----+--------------+--------+--------------+------+
| 2 | 孙悟空 | 100002 | Java | 60 |
| 2 | 孙悟空 | 100002 | Java | 60 |
+----+--------------+--------+--------------+------+
2 rows in set (0.00 sec)
-- 查看真实表中孙悟空的java成绩
mysql> select student.id,student.name,student.sno,course.name,score.sco from student,score,course where student.id=score.student_id and course.id=score.course_id and student.name='孙悟空' and course.name='Java';
+----+-----------+--------+------+------+
| id | name | sno | name | sco |
+----+-----------+--------+------+------+
| 2 | 孙悟空 | 100002 | Java | 60 |
| 2 | 孙悟空 | 100002 | Java | 60 |
+----+-----------+--------+------+------+
2 rows in set (0.00 sec)
--此时就修改好了
但是不是所有的视图都可以进行修改的:
具有以下条件的视图不可以修改:
- 创建视图时使用聚合函数
- 创建视图时使用distinct
- 创建视图使用group by 以及having子句
- 创建视图使用union 或者union all
- 查询列表使用子查询
- 在from子句中引用不可更新的视图
所以通过视图修改数据的情况是很苛刻的,大部分情况下我们还是直接修改真实表即可
1.4 视图的删除
删除视图语法:
drop view view_name;
删除刚才创建的所有视图:
-- 查看创建的视图
mysql> show tables;
+-----------------+
| Tables_in_test |
+-----------------+
| class |
| course |
| score |
| student |
| student1 |
| v_java_or_mysql |
| v_java_sco |
| v_total |
+-----------------+
8 rows in set (0.01 sec)
-- 表名前面带v的都是刚才创建的视图
--删除视图
mysql> drop view v_java_or_mysql,v_java_sco,v_total;
Query OK, 0 rows affected (0.01 sec)
-- 查看
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| class |
| course |
| score |
| student |
| student1 |
+----------------+
5 rows in set (0.00 sec)
那么现在就将刚才创建的视图全部删除啦
1.5 视图的优势
- 简洁性:视图能够把复杂的SQL语句进行封装,变成简单的查询语句
- 安全性:视图可以隐藏表中的敏感数据,比如上面举的银行的例子
- 逻辑数据独立性:即便底层表结构发生变化,只需修改视图定义,无需修改依赖视图的应用程序,实现应用程序与数据库的解耦合
- 列重命名:视图允许用户重命名列,提升数据可读性
二. 用户管理
数据库服务安装完成后会有一个默认的root用户(超级管理员),该用户拥有最高权限能够操纵和管理所有数据库,不过我们有时只希望某个用户操纵和管理当前应用对应的数据库,而不能操纵其他数据库,这时就需要为当前数据库添加用户并指定权限。
![](https://i-blog.csdnimg.cn/direct/babf7ef6b16c49ce89981ba8b417e266.png