Bootstrap

数据库视图

数据库视图

MySQL视图是一种虚拟存在的表,同真实的表一样,视图也由列和行构成,但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表,并且还是在使用视图是动态生成的。数据库中只存放了视图的定义,但没有存放视图中的数据,这些数据都存放在定义视图查询所引用的真实表中。使用视图查询数据时,数据库会从真实表中取出对应的数据。因此,视图中的数据是依赖于真实表中的数据的。一旦真实表中数据发生改变,显示在视图中的数据也会发生改变。

视图可以从原有的表上选取对用户有用的信息,那些对用户没用,或者用户没有权限了解的信息,都可以直接屏蔽掉,作用类似于筛选。

1.视图与数据表的区别如下:

  • 视图不是数据库中真实的表,而是一张虚拟表,其结构和数据是建立在对数据库中真实表的查询基础上的。

  • 存储在数据库中的查询操作sql语句定义了视图的内容,列和行数据来自于视图查询所引用的实际表,引用视图时动态生成这些数据。

  • 视图没有实际的物理记录,不是以数据集的形式存储在数据库中的,他所对应的叔叔实际上是存储在视图所引用的真实表中的。

  • 视图是数据的窗口,而表是内容。表是实际数据的存放单位,而视图只是以不同的显示方式展示数据,其数据来源还是实际表。

  • 视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些 SQL 语句的集合。从安全的角度来看,视图的数据安全性更高,使用视图的用户不接触数据表,不知道表结构。

  • 视图的建立和删除只影响视图本身,不影响对应的基本表。

2.视图的优点:

视图与表在本质上虽然不相同,但视图经过定义以后,结构形式和表一样,可以进行查询、修改、更新

和删除等操作。同时,视图具有如下优点:

  1. 定制用户数据,聚焦特定的数据

在实际的应用过程中,不同的用户可能对不同的数据有不同的要求。

​ 例如,学生基本信息表、课程表和教师信息表等多种表同时存在时,可以根据需求让不同的用户使用各自的数据。学生查看修改自己 基本信息的视图,安排课程人员查看修改课程表和教师信息的视图,教师查看学生信息和课程信息表的视图。

  1. 简化数据操作

在使用查询时,很多时候要使用聚合函数,同时还要显示其他字段的信息,可能还需要关联到其他表,语句可能会很长,如果这个动作频繁发生的话,可以创建视图来简化操作。

  1. 提高数据的安全性

视图是虚拟的,物理上是不存在的。可以只授予用户视图的权限,而不具体指定使用表的权限,来保护基础数据的安全。

  1. 共享所需数据

通过使用视图,每个用户不必都定义和存储自己所需的数据,可以共享数据库中的数据,同样的数据只需要存储一次。

  1. 更改数据格式

通过使用视图,可以重新格式化检索出的数据,并组织输出到其他应用程序中。

  1. 重用 SQL 语句

视图提供的是对查询操作的封装,本身不包含数据,所呈现的数据是根据视图定义从基础表中检索出来的,如果基础表的数据新增或删除,视图呈现的也是更新后的数据。视图定义后,编写完所需的查询,可以方便地重用该视图。

⚠️⚠️

要注意区别视图和数据表的本质,即视图是基于真实表的一张虚拟的表,其数据来源均建立在真实表的基础上。

使用视图的时候,还应该注意以下几点:

  • 创建视图需要足够的访问权限。

  • 创建视图的数目没有限制。

  • 视图可以嵌套,即从其他视图中检索数据的查询来创建视图。

  • 视图不能索引,也不能有关联的触发器、默认值或规则。

  • 视图可以和表一起使用。

  • 视图不包含数据,所以每次使用视图时,都必须执行查询中所需的任何一个检索操作。如果用多个连接和过滤条件创建了复杂的视图或嵌套了视图,可能会发现系统运行性能下降得十分严重。因此,在部署大量视图应用时,应该进行系统测试。

3.视图的创建:

创建视图是指在已经存在的MySQL数据表上建立视图。视图可以建立在一张表中,也可以建立在多张表中。

可以使用CREATE VIEW语句来创建视图。

CREATE VIEW 视图名 AS select...

视图定义中引用的表或视图必须存在。但是,创建完视图后,可以删除定义引用的表或视图。可使用CHECK TABLE 语句检查视图定义是否存在这类问题。

视图定义中允许使用 ORDER BY 语句,但是若从特定视图进行选择,而该视图使用了自己的 ORDER BY语句,则视图定义中的 ORDER BY 将被忽略。

视图定义中不能引用 TEMPORARY 表(临时表),不能创建 TEMPORARY 视图。

WITH CHECK OPTION 的意思是,修改视图时,检查插入的数据是否符合 WHERE 设置的条件。

案例1:创建基于单表的视图

 
mysql> create view myview as select * from emp where deptno=20;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from myview;
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job     | mgr  | hiredate   | sal     | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
|  7369 | SMITH | CLERK   | 7902 | 1980-12-17 |  800.00 | NULL |     20 |
|  7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL |     20 |
|  7788 | SCOTT | ANALYST | 7566 | 1987-07-13 | 3000.00 | NULL |     20 |
|  7876 | ADAMS | CLERK   | 7788 | 1987-07-13 | 1100.00 | NULL |     20 |
|  7902 | FORD  | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL |     20 |
+-------+-------+---------+------+------------+---------+------+--------+
5 rows in set (0.01 sec)

案例2:创建基于多表的视图


mysql> create view myview3 as select d.deptno,d.dname,d.loc,count(e.empno) count,avg(e.sal) avg
    ->
    -> from emp e right outer join dept d
    -> on e.deptno=d.deptno
    -> group by d.deptno,d.dname,d.loc;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from myview3;
+--------+------------+----------+-------+-------------+
| deptno | dname      | loc      | count | avg         |
+--------+------------+----------+-------+-------------+
|     10 | ACCOUNTING | NEW YORK |     3 | 2916.666667 |
|     20 | RESEARCH   | DALLAS   |     5 | 2175.000000 |
|     30 | SALES      | CHICAGO  |     6 | 1566.666667 |
|     40 | OPERATIONS | BOSTON   |     0 |        NULL |
+--------+------------+----------+-------+-------------+
4 rows in set (0.01 sec)

4.视图的查看:

视图一经定义后,就如同查询数据表一样,使用select语句查询视图中的数据,语法和查询基础表的数据一样。

视图用于查询主要应用在以下几个方面:

  • 使用视图重新格式化检索出的数据。

  • 使用视图简化复杂的表连接。

  • 使用视图过滤数据。

可以使用DESCIRBE来查看视图:

DESCRIBE 视图名

或者简写为:

DESC 视图名

案例1:


mysql> desc myview;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| empno    | int         | NO   |     | NULL    |       |
| ename    | varchar(10) | YES  |     | NULL    |       |
| job      | varchar(9)  | YES  |     | NULL    |       |
| mgr      | int         | YES  |     | NULL    |       |
| hiredate | date        | YES  |     | NULL    |       |
| sal      | float(7,2)  | YES  |     | NULL    |       |
| comm     | float(7,2)  | YES  |     | NULL    |       |
| deptno   | int         | YES  |     | NULL    |       |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.01 sec)

mysql> desc myview3;
+--------+--------------+------+-----+---------+-------+
| Field  | Type         | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| deptno | int          | NO   |     | NULL    |       |
| dname  | varchar(14)  | YES  |     | NULL    |       |
| loc    | varchar(13)  | YES  |     | NULL    |       |
| count  | bigint       | NO   |     | 0       |       |
| avg    | double(23,6) | YES  |     | NULL    |       |
+--------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)

由运行结果可以看出,查看视图的字段内容与查看表的字段内容显示的格式是相同的。因此,更能说明视图实际上也是一张数据表了,不同的是,视图中的数据都来自于数据库中已经存在的表。

在MySQL中,show create view语句可以查看视图的详细定义:

SHOW CREATE VIEW 视图名

案例2:


mysql> show create view myview;
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View   | Create View

                                                                                                       | character_set_client | collation_connection |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| myview | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `myview` AS select `emp`.`empno` AS `empno`,`emp`.`ename` AS `ename`,`emp`.`job` AS `job`,`emp`.`mgr` AS `mgr`,`emp`.`hiredate` AS `hiredate`,`emp`.`sal` AS `sal`,`emp`.`comm` AS `comm`,`emp`.`deptno` AS `deptno` from `emp` where (`emp`.`deptno` = 20) | gbk
      | gbk_chinese_ci       |
+--------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.00 sec)

 

mysql> show create view myview3;
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| View    | Create View

                                                                                                             | character_set_client | collation_connection |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
| myview3 | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `myview3` AS select `d`.`deptno` AS `deptno`,`d`.`dname` AS `dname`,`d`.`loc` AS `loc`,count(`e`.`empno`) AS `count`,avg(`e`.`sal`) AS `avg` from (`dept` `d` left join `emp` `e` on((`e`.`deptno` = `d`.`deptno`))) group by `d`.`deptno`,`d`.`dname`,`d`.`loc` | gbk                  | gbk_chinese_ci       |
+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
1 row in set (0.00 sec)	

5.视图的修改:

修改视图是指修改MySQL数据库中存在的视图,当基本表的某些字段发生变化时,可以通过修改视图来保持与基本表一致。

基本语法:

可以使用ALTER VIEW语句来对已有的视图进行修改:

ALTER VIEW  视图名 AS SELECT...

修改视图的定义,除了可以通过 ALTER VIEW 外,也可以使用 DROP VIEW 语句先删除视图,再使用CREATE VIEW 语句来实现。

案例1:


mysql> alter view myview as select * from emp where deptno=30;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from myview;
+-------+--------+----------+------+------------+---------+---------+--------+
| empno | ename  | job      | mgr  | hiredate   | sal     | comm    | deptno |
+-------+--------+----------+------+------------+---------+---------+--------+
|  7499 | ALLEN  | SALESMAN | 7698 | 1981-02-20 | 1600.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER  | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7900 | JAMES  | CLERK    | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
+-------+--------+----------+------+------------+---------+---------+--------+
6 rows in set (0.00 sec)

修改视图的名称可以先将视图删除,然后按照相同的定义语句进行视图的创建,并命名为新的视图名称.

6.视图的更新:

视图是一个虚拟表,实际的数据来自于基本表,所以通过插入,修改和删除操作更新视图中的数据,实质上是在更新视图哦所引用的基本表的数据。

⚠️对视图的更新就是对基本表的更新,因此在修改时,要满足基本表的数据定义。

某些视图是可以更新的。也就是说,可以使用update,delete或者insert等语句更新基本表的内容。对于可更新的视图,视图中的行和基本表的行之间必须具有一对一的关系。

还有一些特定的其他结构,这些结构会使得视图不可更新。更具体的讲,如果视图包含以下结构中的任何一种,他就是不可更新的:

  • 聚合函数sum,min,max等。
  • distinct关键字
  • group by子句
  • having子句
  • union或者union all运算符
  • 位于选着列表中的子查询
  • from子句中的不可更新视图或包含多个表
  • where子句中的子查询,引用from子句中的表

案例1:update


mysql> update myview set sal=1800 where empno=7499;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from myview;
+-------+--------+----------+------+------------+---------+---------+--------+
| empno | ename  | job      | mgr  | hiredate   | sal     | comm    | deptno |
+-------+--------+----------+------+------------+---------+---------+--------+
|  7499 | ALLEN  | SALESMAN | 7698 | 1981-02-20 | 1800.00 |  300.00 |     30 |
|  7521 | WARD   | SALESMAN | 7698 | 1981-02-22 | 1250.00 |  500.00 |     30 |
|  7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 |     30 |
|  7698 | BLAKE  | MANAGER  | 7839 | 1981-05-01 | 2850.00 |    NULL |     30 |
|  7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 |    0.00 |     30 |
|  7900 | JAMES  | CLERK    | 7698 | 1981-12-03 |  950.00 |    NULL |     30 |
+-------+--------+----------+------+------------+---------+---------+--------+
6 rows in set (0.00 sec)

案例2:insert

mysql> INSERT INTO MYVIEW VALUES(9999,'HAHA','ZONGCAI',NULL,'1999-09-
09',9999,NULL,20);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM MYVIEW;
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 1800.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-07-13 | 3000.00 | NULL | 20 |
| 7876 | ADAMS | CLERK | 7788 | 1987-07-13 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
| 9999 | HAHA | ZONGCAI | NULL | 1999-09-09 | 9999.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
6 rows in set (0.00 sec)
mysql> SELECT * FROM EMP WHERE EMPNO=9999;
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 9999 | HAHA | ZONGCAI | NULL | 1999-09-09 | 9999.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
1 row in set (0.00 sec)

案例3:delete

mysql> DELETE FROM MYVIEW WHERE EMPNO=9999;
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM MYVIEW;
+-------+-------+---------+------+------------+---------+------+--------+
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
+-------+-------+---------+------+------------+---------+------+--------+
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 1800.00 | NULL | 20 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL | 20 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-07-13 | 3000.00 | NULL | 20 |
| 7876 | ADAMS | CLERK | 7788 | 1987-07-13 | 1100.00 | NULL | 20 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL | 20 |
+-------+-------+---------+------+------------+---------+------+--------+
5 rows in set (0.00 sec)

7.视图的删除

删除视图是指删除MySQL数据库中已存在的视图。删除视图时,只能删除视图的定义,不会删除数据。

可以使用DROP VIEW语句来删除视图:

DROP VIEW 视图名

DROP VIEW 语句可以一次删除多个视图,但是必须在每个视图上

拥有 DROP 权限。

案例:


mysql> drop view myview;
Query OK, 0 rows affected (0.01 sec)

mysql> drop view myview2;
Query OK, 0 rows affected (0.01 sec)

mysql> drop view myview3;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from myview;
ERROR 1146 (42S02): Table 'test.myview' doesn't exist
;