什么是视图
刚开始看这个词-----脑海中浮现左视图,右视图,俯视图…我试图打死你…
数据库中的视图是一个虚拟表。同真实的表一样,视图包含一系列带有名称的行和列数据。行和列数据来自由定义视图查询所引用的表,并且在引用视图时动态生成。
简单的说,视图是从一个或者多个表中导出的,与表很类似,但又不是,视图是一个虚拟表。在视图中用户可以使用SELECT语句查询数据,以及使用INSERT、UPDATE和DELETE修改记录。视图的功能可追溯到从MySQL 5.0,视图可以使用户操作方便,而且可以隐藏非用户相关数据,可以保障数据库系统的安全。
可以通过视图修改表数据,同时如果表中数据有修改也可以反应到视图中;
视图的创建与使用
语法格式–
create view 视图名 as sql语句;
CREATE表示创建新的视图;
REPLACE表示替换已经创建的视图;
ALGORITHM表示视图选择的算法;
view_name为视图的名称,
column_list为属性列;
SELECT_statement表示SELECT语句;
WITH [CASCADED | LOCAL]CHECK OPTION参数表示视图在更新时保证在视图的权限范围之内。
ALGORITHM的取值有3个,分别是UNDEFINED | MERGE | TEMPTABLE。其中,UNDEFINED表示MySQL将自动选择算法;MERGE表示将使用的视图语句与视图定义合并起来,使得视图定义的某一部分取代语句对应的部分;TEMPTABLE表示将视图的结果存入临时表,然后用临时表来执行语句。
-- 视图的创建
-- 建立一个职位为clerk的视图;
mysql> create view userinfo as select empno 员工编号,ename 员工姓名 ,job 职位 ,deptno 部门编号 from emp where job='clerk' ;
Query OK, 0 rows affected (0.04 sec)
-- 该表等同于
create view userinfo as select empno 员工编号,ename 员工姓名 ,job 职位 ,deptno 部门编号 from emp where job='clerk' ;
Query OK, 0 rows affected (0.04 sec)
-- 视图的使用
mysql> select * from userinfo;
+----------+----------+-------+----------+
| 员工编号 | 员工姓名 | 职位 | 部门编号 |
+----------+----------+-------+----------+
| 7369 | SMITH | CLERK | 20 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7900 | JAMES | CLERK | 30 |
| 7934 | MILLER | CLERK | 10 |
+----------+----------+-------+----------+
5 rows in set (0.02 sec)
向视图中插入信息,删除数据
mysql> insert into userinfo values(1111,'GGGG','CLERK',10);
Query OK, 1 row affected (0.02 sec)
mysql> select * from userinfo;
+----------+----------+-------+----------+
| 员工编号 | 员工姓名 | 职位 | 部门编号 |
+----------+----------+-------+----------+
| 1111 | GGGG | CLERK | 10 |
| 7369 | SMITH | CLERK | 20 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7900 | JAMES | CLERK | 30 |
| 7934 | MILLER | CLERK | 10 |
+----------+----------+-------+----------+
6 rows in set (0.00 sec)
-- 查看原表中的数据---
mysql> select * from emp where empno=1111;
+-------+-------+-------+------+----------+------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+-------+-------+------+----------+------+------+--------+
| 1111 | GGGG | CLERK | NULL | NULL | NULL | NULL | 10 |
+-------+-------+-------+------+----------+------+------+--------+
1 row in set (0.00 sec)
-- 这里要注意 视图中的字段
mysql> DELETE FROM USERINFO WHERE 员工编号=1111;
Query OK, 1 row affected (0.01 sec)
但是问题来了,如果只想插入工作为clerk的职员信息,即如果不是员工为clerk,那么在原表中也不能插入,那怎么办???
先来看上面没有限制要求的 视图-----能否插入非 clerk 员工
mysql> insert into userinfo values(3333,'PPPP','SALESMAN',30);
Query OK, 1 row affected (0.01 sec)
mysql> select * from userinfo;
+----------+----------+-------+----------+
| 员工编号 | 员工姓名 | 职位 | 部门编号 |
+----------+----------+-------+----------+
| 1111 | GGGG | CLERK | 10 |
| 7369 | SMITH | CLERK | 20 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7900 | JAMES | CLERK | 30 |
| 7934 | MILLER | CLERK | 10 |
+----------+----------+-------+----------+
6 rows in set (0.00 sec)
mysql> insert into userinfo values(6666,'PPPP','clerk',30);
Query OK, 1 row affected (0.02 sec)
mysql> select * from userinfo;
+----------+----------+-------+----------+
| 员工编号 | 员工姓名 | 职位 | 部门编号 |
+----------+----------+-------+----------+
| 1111 | GGGG | CLERK | 10 |
| 6666 | PPPP | clerk | 30 |
| 7369 | SMITH | CLERK | 20 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7900 | JAMES | CLERK | 30 |
| 7934 | MILLER | CLERK | 10 |
+----------+----------+-------+----------+
7 rows in set (0.00 sec)
在mysql的sql语句中对wherez子句后中加入 with check option 来限制只能添加where 限制的字段类型的数据 ,
-- create or replace 创建或替换
mysql> create or replace view userinfo as select empno 员工编号,ename 员工姓名 ,job 职位 ,deptno 部门编号 from emp where job='clerk' with check option ;
Query OK, 0 rows affected (0.04 sec)
-----插入数据
mysql> insert into userinfo values(7777,'QQQQ','SALESMAN',30);
ERROR 1369 (HY000): CHECK OPTION failed 'gavin.userinfo'
mysql>
mysql> insert into userinfo values(7777,'PPQQQQ','CLERK',30);
Query OK, 1 row affected (0.03 sec)
mysql> select * from userinfo;
+----------+----------+-------+----------+
| 员工编号 | 员工姓名 | 职位 | 部门编号 |
+----------+----------+-------+----------+
| 1111 | GGGG | CLERK | 10 |
| 6666 | PPPP | clerk | 30 |
| 7369 | SMITH | CLERK | 20 |
| 7777 | PPQQQQ | CLERK | 30 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7900 | JAMES | CLERK | 30 |
| 7934 | MILLER | CLERK | 10 |
+----------+----------+-------+----------+
8 rows in set (0.00 sec)
视图的作用
与直接从数据表中读取相比,视图有以下优点:
1.简单化
使得用户看到的就是他需要的,不需要过多的查询条件,因为实现就已经整好了;
2.安全性
通过视图,用户只能查询和修改他们所能见到的数据。数据库中的其他数据则既看不见也取不到。
3,还可以细化到具体的数据库对象上.
数据库授权命令可以使每个用户对数据库的检索限制到特定的数据库对象上,但不能授权到数据库特定行和特定的列上。
通过视图,用户可以被限制在数据的不同子集上:
- 使用权限可被限制在基表的行的子集上。
- 使用权限可被限制在基表的列的子集上。
- 使用权限可被限制在基表的行和列的子集上。
- 使用权限可被限制在多个基表的连接所限定的行上。
- 使用权限可被限制在基表中的数据的统计汇总上。
- 使用权限可被限制在另一视图的一个子集上,或是一些视图和基表合并后的子集上。
在单表上创建视图
mysql> create or replace view myview as select empno ,ename,job,deptno from emp where deptno =20;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from myview;
+-------+-------+---------+--------+
| empno | ename | job | deptno |
+-------+-------+---------+--------+
| 7369 | SMITH | CLERK | 20 |
| 7566 | JONES | MANAGER | 20 |
| 7788 | SCOTT | ANALYST | 20 |
| 7789 | Gavin | CLERK | 20 |
| 7876 | ADAMS | CLERK | 20 |
| 7902 | FORD | ANALYST | 20 |
+-------+-------+---------+--------+
6 rows in set (0.00 sec)
在多表上创建视图
mysql> create or replace view myview1 as select e.empno ,e.ename,e.deptno,e1.mgr,e1.ename '领导' from emp e inner join emp e1 on e.empno =e1.mgr ;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from myview1;
+-------+-------+--------+------+--------+
| empno | ename | deptno | mgr | 领导 |
+-------+-------+--------+------+--------+
| 7902 | FORD | 20 | 7902 | SMITH |
| 7698 | BLAKE | 30 | 7698 | ALLEN |
| 7698 | BLAKE | 30 | 7698 | WARD |
| 7698 | BLAKE | 30 | 7698 | MARTIN |
| 7566 | JONES | 20 | 7566 | SCOTT |
| 7698 | BLAKE | 30 | 7698 | TURNER |
| 7788 | SCOTT | 20 | 7788 | ADAMS |
| 7698 | BLAKE | 30 | 7698 | JAMES |
| 7566 | JONES | 20 | 7566 | FORD |
| 7782 | CLARK | 10 | 7782 | MILLER |
+-------+-------+--------+------+--------+
10 rows in set (0.00 sec)
查看视图
视图可以理解为一张虚拟表,也可以查看该视图的字段信息,创建信息
mysql> desc myview1;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| empno | int | NO | | NULL | |
| ename | varchar(10) | YES | | NULL | |
| deptno | int | YES | | NULL | |
| mgr | int | YES | | NULL | |
| 领导 | varchar(10) | YES | | NULL | |
+--------+-------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql> show create view myview1\G
*************************** 1. row ***************************
View: myview1
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`gavin`@`%` SQL SECURITY DEFINER VIEW `myview1` AS select `e`.`EMPNO` AS `empno`,`e`.`ENAME` AS `ename`,`e`.`DEPTNO` AS `deptno`,`e1`.`MGR` AS `mgr`,`e1`.`ENAME` AS `领导` from (`emp` `e` join `emp` `e1` on((`e`.`EMPNO` = `e1`.`MGR`)))
character_set_client: gbk
collation_connection: gbk_chinese_ci
1 row in set (0.00 sec)
---- 查看视图的状态
mysql> show table status like 'myview1' \G
*************************** 1. row ***************************
Name: myview1 -- 视图名
Engine: NULL
Version: NULL
Row_format: NULL
Rows: NULL
Avg_row_length: NULL
Data_length: NULL
Max_data_length: NULL
Index_length: NULL
Data_free: NULL
Auto_increment: NULL
Create_time: 2021-09-08 08:39:56
Update_time: NULL
Check_time: NULL
Collation: NULL
Checksum: NULL
Create_options: NULL
Comment: VIEW ---- 说明这是一张视图,
1 row in set (0.00 sec)
// 其他信息都为null说明这是一张虚拟表
-- 再来查看表的状态
mysql> show table status like 'emp'\G
*************************** 1. row ***************************
Name: emp
Engine: InnoDB
Version: 10
Row_format: Dynamic
Rows: 21
Avg_row_length: 780
Data_length: 16384
Max_data_length: 0
Index_length: 16384
Data_free: 0
Auto_increment: NULL
Create_time: 2021-09-03 19:13:24
Update_time: 2021-09-07 21:34:53
Check_time: NULL
Collation: utf8mb4_0900_ai_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
-- 正常表 会包含很多信息
从查询的结果来看,视图里的信息包含了存储引擎、创建时间等,Comment信息为空,这就是视图和表的区别。
在元信息表里也可以查看视图的信息
mysql> select * from information_schema.views where table_name= 'myview1' \G
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: gavin
TABLE_NAME: myview1
VIEW_DEFINITION: select `e`.`EMPNO` AS `empno`,`e`.`ENAME` AS `ename`,`e`.`DEPTNO` AS `deptno`,`e1`.`MGR` AS `mgr`,`e1`.`ENAME` AS `领导` from (`gavin`.`emp` `e` join `gavin`.`emp` `e1` on((`e`.`EMPNO` = `e1`.`MGR`)))
CHECK_OPTION: NONE -- 检查信息
IS_UPDATABLE: YES -- 视图权限 可更新
DEFINER: gavin@% -- 定义者--gavin
SECURITY_TYPE: DEFINER --- 安全类型 --- 定义者所有
CHARACTER_SET_CLIENT: gbk
COLLATION_CONNECTION: gbk_chinese_ci
1 row in set (0.00 sec)
修改视图字段
上面的代码中已经出现了一种方式------
方式一-----
--格式--
create or replace view 视图名 as .....
mysql> create or replace view myview as select empno ,ename,job,deptno from emp where deptno =20;
方式二-----
alter view 视图名 as ......
mysql> alter view myview as select * from emp where deptno =10 ;
Query OK, 0 rows affected (0.01 sec)
更新视图与删除数据
视图中的数据与表中的数据操作方法一致
-- 查看修改之前的数据
mysql> select * from myview ;
+-------+--------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+------+--------+
| 1111 | GGGG | CLERK | NULL | NULL | NULL | NULL | 10 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7893 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+------+--------+
4 rows in set (0.00 sec)
修改和删除数据
mysql> select * from myview ;
+-------+--------+-----------+------+------------+---------+------+--------+
| EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
+-------+--------+-----------+------+------------+---------+------+--------+
| 1111 | GGGG | CLERK | NULL | NULL | NULL | NULL | 10 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL | 10 |
| 7893 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL | 10 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300.00 | NULL | 10 |
+-------+--------+-----------+------+------------+---------+------+--------+
4 rows in set (0.00 sec)
对视图myview更新/删除数据后,基本表emp的内容也更新
删除视图
mysql> drop view myview ;
Query OK, 0 rows affected (0.01 sec)
视图更新/删除数据失败是什么原因???
当视图中包含有如下内容时,视图的更新操作将不能被执行:
(1)视图中不包含基表中被定义为非空的列。
(2)在定义视图的SELECT语句后的字段列表中使用了数学表达式。
(3)在定义视图的SELECT语句后的字段列表中使用聚合函数。
(4)在定义视图的SELECT语句中使用了DISTINCT、UNION、TOP、GROUP BY或HAVING子句。
-- 建立视图
mysql> create or replace view myview as select empno ,group_concat(ename) ,job ,avg(ifnull(sal,0)+ifnull(comm,0)) from emp group by deptno ;
Query OK, 0 rows affected (0.03 sec)
-- 查看视图
mysql> select * from myview;
+-------+------------------------------------------------------------+----------+-----------------------------------+
| empno | group_concat(ename) | job | avg(ifnull(sal,0)+ifnull(comm,0)) |
+-------+------------------------------------------------------------+----------+-----------------------------------+
| 1111 | GGGG,KING,MILLER | CLERK | 2516.666667 |
| 7369 | SMITH,JONES,SCOTT,Gavin,ADAMS,FORD | CLERK | 2312.500000 |
| 2222 | PPPP,PPPP,PPPP,ALLEN,WARD,MARTIN,BLAKE,PPQQQQ,TURNER,JAMES | SALESMAN | 1160.000000 |
| 7367 | NULL | NULL | 0.000000 |
+-------+------------------------------------------------------------+----------+-----------------------------------+
4 rows in set (0.00 sec)
修改数据–
ERROR 1146 (42S02): Table 'gavin.view' doesn't exist
mysql> update myview set job='salesman' where empno=7367;
ERROR 1288 (HY000): The target table myview of the UPDATE is not updatable
mysql> delete from myview where empno=7367;
ERROR 1288 (HY000): The target table myview of the DELETE is not updatable