
一、视图
当我们需要多次使用同一个复杂的 SQL 语句进行查询时,可以使用视图来对 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;
为了简化复杂 SQL 语句,我们可以使用视图进行包装:
-- 创建视图
CREATE VIEW v_Java_or_MySQL AS
SELECT DISTINCT s.id, s.name, s1.sco AS java_sco, s2.sco AS mysql_sco
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;
查询学生的姓名和总分(隐藏学号和各科成绩):
-- 直接使用真实表查询
mysql> SELECT s.name, SUM(sc.sco) FROM student s, score sc WHERE s.id = sc.student_id GROUP BY s.name;
-- 使用视图
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;
SELECT name FROM v_total;
如果直接使用真实表进行查询,想要查看什么信息就只需要加上需要查看的字段即可。但是假设现在是一个银行系统,如果能够这样随机查看想要查看的内容,那么就没有办法保证信息的安全性了。视图可以隐藏表中的敏感数据。
视图还可以与真实表进行表连接查询:
mysql> SELECT * FROM student, v_total WHERE student.name = v_total.name;
1.3 修改数据
对真实表的数据进行修改,会影响视图,是因为视图的本质并没有保存数据,可以理解为保存的是查询语句。当我使用视图时就会调用保存的查询语句返回结果,所以真实表的数据不管怎么变,我每一次使用视图都是一次新的查询。
将孙悟空的 Java 成绩修改为 99 分:
-- 修改成绩
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');
不仅通过真实表修改数据会影响视图,通过视图修改数据也会影响到基表:
-- 创建视图
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';
-- 通过视图修改数据
UPDATE v_java_sco SET sco = 60;
但是不是所有的视图都可以进行修改的:
具有以下条件的视图不可以修改:
- 创建视图时使用聚合函数
- 创建视图时使用 DISTINCT
- 创建视图使用 GROUP BY 以及 HAVING 子句
- 创建视图使用 UNION 或者 UNION ALL
- 查询列表使用子查询在 FROM 子句中引用不可更新的视图
所以通过视图修改数据的情况是很苛刻的,大部分情况下我们还是直接修改真实表即可。
1.4 删除视图
删除视图语法:
DROP VIEW view_name;
删除刚才创建的所有视图:
-- 查看创建的视图
SHOW TABLES;
-- 删除视图
DROP VIEW v_Java_or_MySQL, v_java_sco, v_total;
1.5 视图的优点
- 简单性:视图可以将复杂的 SQL 语句进行封装,变成一个简单的查询语句。
- 安全性:视图可以隐藏表中的敏感数据,比如上面举的银行的例子。
- 逻辑数据独立性:即使底层表结构发生变化,只需要修改视图定义,不需要修改依赖视图的应用程序,使用到应用程序与数据库的解耦合。
- 重命名列:视图允许用户重命名列,增强数据可读性。
二、用户
数据库服务安装完成后会存在一个默认的 root 用户(超级管理员),该用户拥有最高权限可以操纵和管理所有数据库。但是此时我们只希望某个用户操纵和管理当前应用对应的数据库,而不能操纵和管理其他的数据库,这个时候我们就需要为当前数据库添加一个用户并指定用户的权限。

对于上图中的用户来说,root 用户可以操纵所有的数据库,普通用户分别可以操纵 DB1 和 DB3,而只读用户分别只能访问 DB3 和 DB4。
2.1 查看用户
在 MySQL 中,用户的信息保存在系统数据库中的 user 表中,通过 SELECT 语句进行查看:
mysql> USE mysql;
mysql> SHOW TABLES;
mysql> SELECT host, user, authentication_string FROM user;
- host:表示谁可以登录。
- user:表示用户名。
- authentication_string:表示加密后的用户密码。
2.2 创建用户
创建用户语法:
CREATE USER 'user_name'@'host_name' IDENTIFIED BY 'auth_string';
'user_name'@'host_name'是一个用户描述的方式。'user_name'部分就是用来登录 MySQL 的用户名。'host_name'部分是可以登录的主机名或者 IP,只有指定的机器才能访问当前 MySQL。如果不指定host_name相当于'user_name'@'%'表示所有主机都可以连接到数据库,这样可能会导致安全问题。'auth_string'是密码的明文。host_name可以通过子网掩码设置主机范围,比如192.168.10.1/24。
创建用户:
mysql> CREATE USER 'sunny'@'localhost' IDENTIFIED BY '8888';
创建一个新用户,允许从 192.168.10.1/24 网段登录:
-- 创建用户
CREATE USER 'rain'@'192.168.10.1/24' IDENTIFIED BY '666';
创建完成后,使用新用户登录试试:
# 成功登录示例
mysql -usunny -p
# 失败示例(IP 不在允许网段)
mysql -urain -p
ERROR 1045 (28000): Access denied for user 'rain'@'localhost'
2.3 修改密码
修改密码语法:
-- 方法 1
ALTER USER 'user_name'@'host_name' IDENTIFIED BY 'auth_string';
-- 方法 2
SET PASSWORD FOR 'user_name'@'host_name' = 'auth_string';
-- 为当前用户设置密码
SET PASSWORD = 'auth_string';
以 root 超级管理员身份登录,为 'sunny'@'localhost' 用户设置密码:
-- 修改密码
ALTER USER 'sunny'@'localhost' IDENTIFIED BY '6';
2.4 删除用户
删除用户语法:
DROP USER 'user_name'@'host_name';
删除刚才创建的 rain 用户:
mysql> DROP USER 'rain'@'192.168.10.1/24';
三、权限
用户创建好之后,我们需要给用户赋予一些专属的权限。其中 ALL 表示所有的权限,root 管理员则拥有这样的权限。

对于刚创建的用户是没有任何权限的:比如 sunny 用户。
3.1 查看当前用户权限
查看语法:
SHOW GRANTS FOR 'user_name'@'host_name';
查看 sunny 用户拥有的权限:
mysql> SHOW GRANTS FOR 'sunny'@'localhost';
USAGE 表示没有任何权限。
3.2 添加权限
添加权限语法:
GRANT priv_type ON priv_level TO 'user_name'@'host_name';
- priv_type:权限类型。
- priv_level:
* | *.* | db_name.* | db_name.tbl_name | tbl_name。*.*表示所有数据库下的所有表。
为 sunny 用户授权于查看 test 数据的权限:
-- 授予权限
GRANT SELECT ON test.* TO 'sunny'@'localhost';
-- 查看权限
SHOW GRANTS FOR 'sunny'@'localhost';
为 sunny 用户授权 test 数据库所有权限:
mysql> GRANT ALL ON test.* TO 'sunny'@'localhost';
3.3 回收权限
能够为用户授予权限,当前也能够回收权限啦,回收权限语法:
REVOKE priv_type ON priv_level FROM 'user_name'@'host_name';
回收 sunny 用户的对于 test 数据库的权限:
mysql> REVOKE ALL ON *.* FROM 'sunny'@'localhost';
注意事项: 给用户赋予权限和收回权限时都需要注意当前用户是否有赋予其他用户权限的能力和收回其他用户权限的能力,所以当我们最好使用 root 超级管理员来对其他用户进行操作。


