概念
视图(View)是数据库中的虚拟表,基于一个或多个实际表的查询结果生成。视图不存储数据,仅保存查询定义,每次访问时动态执行查询。视图的主要作用包括简化复杂查询、隐藏敏感数据、提供统一的数据访问接口。
视图的数据变化会影响到基表,基表的数据变化也会影响到视图。
创建视图
语法:
sql
create view 视图名 as select语句;
例如我们想要在scott数据库中,查询一个员工的姓名和对应的部门名称:
sql
mysql> select ename,dname from emp,dept where emp.deptno=dept.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.10 sec)
查询语句非常简易,但是如果这个要频繁查询也是一件麻烦的事。
我们可以用这个查询结构构建一个新的表,这样就能直接从新表获取员工名和部门名。但是这样一来,原来emp和dept表中数据变化,新表不会立刻变化,需要手动更新,这就稍显麻烦。
因此,除了表之外我们要需要一个新的存储数据的结构,也就是视图。他能帮助我们简化查询步骤,并且数据会随着基表变化而变化。
如我们利用上面的查询结果建立视图:
sql
mysql> create view myview as select ename,dname from emp,dept where emp.deptno=dept.deptno;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from myview;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING |
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
修改视图
我们现在尝试对视图数据进行修改:
sql
mysql> update myview set ename=lcase(ename) where ename='CLARK';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select ename,dname from emp,dept where emp.deptno=dept.deptno;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| clark | ACCOUNTING | ---'CLARK' -> 'clark'
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
可以看到基表数据发生了改变。
那么我们再对基表数据修改:
sql
mysql> update emp set ename=ucase(ename) where ename='clark';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from myview;
+--------+------------+
| ename | dname |
+--------+------------+
| SMITH | RESEARCH |
| ALLEN | SALES |
| WARD | SALES |
| JONES | RESEARCH |
| MARTIN | SALES |
| BLAKE | SALES |
| CLARK | ACCOUNTING | --'clark' -> 'CLARK'
| SCOTT | RESEARCH |
| KING | ACCOUNTING |
| TURNER | SALES |
| ADAMS | RESEARCH |
| JAMES | SALES |
| FORD | RESEARCH |
| MILLER | ACCOUNTING |
+--------+------------+
14 rows in set (0.00 sec)
可以看到视图数据同样修改了。
删除视图
语法:
sql
drop view 视图名;
我们把刚刚创建的视图删除:
sql
mysql> show tables;
+-----------------+
| Tables_in_scott |
+-----------------+
| dept |
| emp |
| exam |
| myview |
| salgrade |
| stu |
+-----------------+
6 rows in set (0.00 sec)
mysql> drop view myview;
Query OK, 0 rows affected (0.13 sec)
mysql> show tables;
+-----------------+
| Tables_in_scott |
+-----------------+
| dept |
| emp |
| exam |
| salgrade |
| stu |
+-----------------+
5 rows in set (0.00 sec)
此时看看会不会影响原表数据:

并不会!
视图的规则和限制
- 与表一样,必须唯一命名(不能出现同名视图或表名)
- 创建视图数目无限制,但要考虑复杂查询创建为视图之后的性能影响
- 视图不能添加索引,也不能有关联的触发器或者默认值
- 视图可以提高安全性,必须具有足够的访问权限
- order by可以用在视图中,但是如果从该视图检索数据select 中也含有order by,那么该视图中的order by将被覆盖
- 视图可以和表一起使用
OJ
来一道OJ练习一下:
针对actor表创建视图actor_name_view
描述
针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:
sql
CREATE TABLE actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update datetime NOT NULL);
后台会插入2条数据:
insert into actor values ('1', 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), ('2', 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');
然后打印视图名字和插入的数据
示例:
sql
输入:
drop table if exists actor;
CREATE TABLE actor (
actor_id smallint(5) NOT NULL PRIMARY KEY,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update datetime NOT NULL);
insert into actor values ('1', 'PENELOPE', 'GUINESS', '2006-02-15 12:34:33'), ('2', 'NICK', 'WAHLBERG', '2006-02-15 12:34:33');
输出:
['first_name_v', 'last_name_v']
PENELOPE|GUINESS
NICK|WAHLBERG
代码:
sql
create view
actor_name_view as
select
first_name first_name_v,
last_name last_name_v
from
actor;
