一、基本概念

1.1 基本定义

视图:MySQL从5.0.1版本开始提供视图功能。一种虚拟 存在的表,行和列的数据来自定义视图的查询中使用的表 ,并且是在使用视图时动态生成的,只保存了sql逻辑,不保存查询结果

比如:舞蹈班和普通班级的对比
创建语法的关键字 是否实际占用物理空间 使用

1.2 应用场景

  • 多个地方用到同样的查询结果
  • 该查询结果使用的sql语句较复杂


1.3 示例

#案例:查询姓张的学生名和专业名

  1. SELECT stuname,majorname
  2. FROM stuinfo s
  3. INNER JOIN major m ON s.`majorid`= m.`id`
  4. WHERE s.`stuname` LIKE '张%';
  5. CREATE VIEW v1
  6. AS
  7. SELECT stuname,majorname
  8. FROM stuinfo s
  9. INNER JOIN major m ON s.`majorid`= m.`id`;
  10. SELECT * FROM v1 WHERE stuname LIKE '张%';

1.4 作用

  • 重用sql语句
  • 简化复杂的sql操作,不必知道它的查询细节
  • 保护数据,提高安全性

1.5 视图和表的对比

视图 create view 只是保存了sql逻辑 增删改查,只是一般不能增删改
create table 保存了数据 增删改查

二、具体操作

2.1 创建视图

语法:
create view 视图名
as
查询语句;

USE myemployees;

#1.查询姓名中包含a字符的员工名、部门名和工种信息
#①创建

  1. CREATE VIEW myv1
  2. AS
  3. SELECT last_name,department_name,job_title
  4. FROM employees e
  5. JOIN departments d ON e.department_id = d.department_id
  6. JOIN jobs j ON j.job_id = e.job_id;

image.png
#②使用

  1. SELECT * FROM myv1 WHERE last_name LIKE '%a%';

image.png

#2.查询各部门的平均工资级别

#①创建视图查看每个部门的平均工资

  1. CREATE VIEW myv2
  2. AS
  3. SELECT AVG(salary) ag,department_id
  4. FROM employees
  5. GROUP BY department_id;

②使用

  1. SELECT myv2.`ag`,g.grade_level
  2. FROM myv2
  3. JOIN job_grades g
  4. ON myv2.`ag` BETWEEN g.`lowest_sal` AND g.`highest_sal`;


#3.查询平均工资最低的部门信息

  1. SELECT * FROM myv2 ORDER BY ag LIMIT 1;


#4.查询平均工资最低的部门名和工资

  1. CREATE VIEW myv3
  2. AS
  3. SELECT * FROM myv2 ORDER BY ag LIMIT 1;
  4. SELECT d.*,m.ag
  5. FROM myv3 m
  6. JOIN departments d
  7. ON m.`department_id`=d.`department_id`;





2.2 视图的修改

方式一:

create or replace view 视图名
as
查询语句;

  1. SELECT * FROM myv3
  2. CREATE OR REPLACE VIEW myv3
  3. AS
  4. SELECT AVG(salary),job_id
  5. FROM employees
  6. GROUP BY job_id;

方式二:

语法: alter view 视图名
as
查询语句;

  1. ALTER VIEW myv3
  2. AS
  3. SELECT * FROM employees;

2.3 删除视图

语法:drop view 视图名,视图名,…;

  1. DROP VIEW emp_v1,emp_v2,myv3;
  • 首先用户需要有删除的权限,示例是用root基本都有权限

    2.4 查看视图

    ```sql DESC myv3;

SHOW CREATE VIEW myv3; —更具体的信息,包括创建后的大部分信息

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2196885/1622990895419-145d8ff4-221f-4760-beea-5a0b42d8c987.png#clientId=u04235208-2a24-4&from=paste&height=59&id=ucde2b2bf&margin=%5Bobject%20Object%5D&name=image.png&originHeight=59&originWidth=969&originalType=binary&ratio=1&size=63331&status=done&style=none&taskId=u428aa8cc-2df3-4713-8cd0-2305fd0140e&width=969)<br />
  2. <a name="ViRxB"></a>
  3. ### 2.5 视图的更新
  4. <br />先创建两个视图
  5. ```sql
  6. CREATE OR REPLACE VIEW myv1
  7. AS
  8. SELECT last_name,email,salary*12*(1+IFNULL(commission_pct,0)) "annual salary"
  9. FROM employees;
  10. CREATE OR REPLACE VIEW myv1
  11. AS
  12. SELECT last_name,email
  13. FROM employees;

SELECT FROM myv1;
SELECT
FROM employees;

2.5.1 插入

  1. INSERT INTO myv1 VALUES('张飞','zf@qq.com');
  • 会对原始表有修改!
  • 所以往往会给视图设置权限

2.5.2 修改

  1. UPDATE myv1 SET last_name = '张无忌' WHERE last_name='张飞';


2.5.3 删除

  1. DELETE FROM myv1 WHERE last_name = '张无忌';


具备以下特点的视图不允许更新



#①包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all

  1. CREATE OR REPLACE VIEW myv1
  2. AS
  3. SELECT MAX(salary) m,department_id
  4. FROM employees
  5. GROUP BY department_id;
  6. SELECT * FROM myv1;
  7. #更新
  8. UPDATE myv1 SET m=9000 WHERE department_id=10;

image.png
#②常量视图

  1. CREATE OR REPLACE VIEW myv2
  2. AS
  3. SELECT 'john' NAME;
  4. SELECT * FROM myv2;
  5. #更新
  6. UPDATE myv2 SET NAME='lucy';


#③Select中包含子查询

  1. CREATE OR REPLACE VIEW myv3
  2. AS
  3. SELECT department_id,(SELECT MAX(salary) FROM employees) 最高工资
  4. FROM departments;
  5. #更新
  6. SELECT * FROM myv3;
  7. UPDATE myv3 SET 最高工资=100000;



#④join

  1. CREATE OR REPLACE VIEW myv4
  2. AS
  3. SELECT last_name,department_name
  4. FROM employees e
  5. JOIN departments d
  6. ON e.department_id = d.department_id;
  7. #更新
  8. SELECT * FROM myv4;
  9. UPDATE myv4 SET last_name = '张飞' WHERE last_name='Whalen';
  10. INSERT INTO myv4 VALUES('陈真','xxxx');

image.png
#⑤from一个不能更新的视图

  1. CREATE OR REPLACE VIEW myv5
  2. AS
  3. SELECT * FROM myv3;
  4. #更新
  5. SELECT * FROM myv5;
  6. UPDATE myv5 SET 最高工资=10000 WHERE department_id=60;

image.png
#⑥where子句的子查询引用了from子句中的表

  1. CREATE OR REPLACE VIEW myv6
  2. AS
  3. SELECT last_name,email,salary
  4. FROM employees
  5. WHERE employee_id IN(
  6. SELECT manager_id
  7. FROM employees
  8. WHERE manager_id IS NOT NULL
  9. );
  10. #更新
  11. SELECT * FROM myv6;
  12. UPDATE myv6 SET salary=10000 WHERE last_name = 'k_ing';

三、案例 #一、创建视图emp_v1,要求查询电话号码以‘011’开头的员工姓名和工资、邮箱

  1. CREATE OR REPLACE VIEW emp_v1
  2. AS
  3. SELECT last_name,salary,email
  4. FROM employees
  5. WHERE phone_number LIKE '011%';

#二、创建视图emp_v2,要求查询部门的最高工资高于12000的部门信息

  1. CREATE OR REPLACE VIEW emp_v2
  2. AS
  3. SELECT MAX(salary) mx_dep,department_id
  4. FROM employees
  5. GROUP BY department_id
  6. HAVING MAX(salary)>12000;
  7. SELECT d.*,m.mx_dep
  8. FROM departments d
  9. JOIN emp_v2 m
  10. ON m.department_id = d.`department_id`;

image.png