视图
视图是一个虚拟表, 其内容由查询定义. 同真实的表一样, 视图包含一系列带有名称的列和行数据. 视图的数据变化会影响到基表, 基表的数据变化也会影响到视图.
基本使用
创建视图
sql
create view 视图名 as select语句;
删除视图
sql
drop view 视图名;
比如当前有一个员工表和部门表:
sql
desc emp
+----------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------------------+------+-----+---------+-------+
| empno | int(6) unsigned zerofill | NO | | <null> | |
| ename | varchar(10) | YES | | <null> | |
| job | varchar(9) | YES | | <null> | |
| mgr | int(4) unsigned zerofill | YES | | <null> | |
| hiredate | datetime | YES | | <null> | |
| sal | decimal(7,2) | YES | | <null> | |
| comm | decimal(7,2) | YES | | <null> | |
| deptno | int(2) unsigned zerofill | YES | | <null> | |
+----------+--------------------------+------+-----+---------+-------+
desc dept
+--------+--------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------------------+------+-----+---------+-------+
| deptno | int(2) unsigned zerofill | NO | | <null> | |
| dname | varchar(14) | YES | | <null> | |
| loc | varchar(13) | YES | | <null> | |
+--------+--------------------------+------+-----+---------+-------+
我想查看(员工名, 部门名), 通过内连接就可以完成:
sql
select ename, dname
from emp inner join dept
on emp.deptno=dept.deptno
+--------+------------+
| ename | dname |
+--------+------------+
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
假如我现在想查看FORD的部分, 加上where条件即可:
sql
select ename, dname from emp inner join dept on emp.deptno=dept.deptno where ename="FORD"
+-------+----------+
| ename | dname |
+-------+----------+
| FORD | RESEARCH |
+-------+----------+
但是现在我想频繁的去查询数据, 每次输入上面那一行SQL就很麻烦, 所以可以把上面的查询结果组织成一张虚拟表, 即视图, 方便以后的使用:
sql
create view myview as
select ename, dname from emp inner join dept on emp.deptno=dept.deptno
show tables可以发现数据库中多了一张myview表:
sql
show tables;
+-----------------+
| Tables_in_scott |
+-----------------+
| dept |
| emp |
| myview |
| salgrade |
+-----------------+
之后的操作就可以在myview视图上完成了:
sql
select * from myview where ename="FORD"
+-------+----------+
| ename | dname |
+-------+----------+
| FORD | RESEARCH |
+-------+----------+
注意修改视图会影响基表数据, 修改基表数据也会影响视图
- 修改了视图, 对基表数据有影响:
sql
//把WARD转为小写
update myview set ename="ward" where ename="WARD"
//基表数据也变了(第一行的ename)
select * from emp
+-------+--------+-----------+--------+---------------------+---------+---------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+--------+-----------+--------+---------------------+---------+---------+--------+
| 7521 | ward | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250.00 | 500.00 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | <null> | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | <null> | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 6450.00 | <null> | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 4800.00 | <null> | 20 |
| 7839 | KING | PRESIDENT | <null> | 1981-11-17 00:00:00 | 7200.00 | <null> | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00 | 1500.00 | 0.00 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | <null> | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 | 950.00 | <null> | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | <null> | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 3500.00 | <null> | 10 |
+-------+--------+-----------+--------+---------------------+---------+---------+--------+
- 同样的, 修改了基表, 对视图有影响:
sql
update emp set ename="WARD" where ename="ward"
update dept set dname="accounting" where dname="ACCOUNTING"
select * from myview
+--------+------------+
| ename | dname |
+--------+------------+
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | accounting |
| SCOTT | RESEARCH |
| KING | accounting |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | accounting |
+--------+------------+
View 就像是给在程序员操作层面上提供的表级别的缓存, 把我们想看到的数据以表的形式呈现出来, 方便我们快速的进行CURD(主要是查).
视图规则和限制
- 与表一样, 必须唯一命名(不能出现同名视图或表名)
- 创建视图数目无限制, 但要考虑复杂查询创建为视图之后的性能影响.
- 视图不能添加索引, 也不能有关联的触发器或者默认值
- 视图可以提高安全性, 必须具有足够的访问权限
- order by 可以用在视图中, 但是如果从该视图检索数据 select 中也含有 order by ,那么该视图中的 order by 将被覆盖
- 视图可以和表一起使用(视图可以和普通表进行连接, 笛卡尔积等)
补充
MySQL 5.7 及以前 的情况:
- 创建表: 产生 .frm + .ibd文件
- 创建视图: 产生 .frm文件(但不产生 .ibd)
从 MySQL 8.0 开始:
所有元数据(包括视图)都存储在 数据字典表, 不再生成 .frm 文件.
