(11) 视图
最后更新于:2022-04-01 23:40:04
**目录**
[TOC]
# 1 View的应用
在使用MySQL数据库的时候,你会使用各种不同的SQL叙述来执行查询与维护的工作。数据库在运作一段时间后,你会发觉不论是查询与维护的叙述,都可能会出现一些类似、而且很常使用的SQL叙述:
[![mysql_11_snap_01](http://box.kancloud.cn/2015-09-15_55f7ef13444e1.png)](http://box.kancloud.cn/2015-09-15_55f7ef13444e1.png)
以上列的查询叙述来说,虽然它并不是很复杂,只是一个加入排序设定的一般查询而已。可是如果常常会执行这样的查询,你每次都要输入这个查询叙述再执行它;就算你把这个查询叙述储存为文字档保存起来,需要的时候再开启档案使用,这样做的话是比较方便一些,不过还是很麻烦,而且比较没有灵活性。
如果在数据库的应用中,出现这种很常执行的查询叙述时,你可以在MySQL数据库中建立一种“View”元件,View元件用来保存一段你指定的查询叙述:
[![mysql_11_snap_02](http://box.kancloud.cn/2015-09-15_55f7ef142092a.png)](http://box.kancloud.cn/2015-09-15_55f7ef142092a.png)
建立好需要的View元件以后,除了有一些限制外,它使用起来就像是一个表格,所以当你需要执行这样的查询时,可以在查询叙述的“FROM”子句指定一个View元件:
[![mysql_11_snap_03](http://box.kancloud.cn/2015-09-15_55f7ef14c7b61.png)](http://box.kancloud.cn/2015-09-15_55f7ef14c7b61.png)
也有很多人称“View”元件是一种“虚拟表格”,因为它不是一个真正储存纪录资料的表格,可是它又跟表格的用法类似。所以如果有需要的话,你也可以使用View元件回传的纪录资料,执行统计、分组与其它需要的处理:
[![mysql_11_snap_04](http://box.kancloud.cn/2015-09-15_55f7ef154580f.png)](http://box.kancloud.cn/2015-09-15_55f7ef154580f.png)
View元件就像是一个表格,大部份使用表格可以完成的工作,也可以套用在View元件。所以把View元件和表格一起放在“FROM”子句中,执行需要的结合查询也是可以的:
[![mysql_11_snap_05](http://box.kancloud.cn/2015-09-15_55f7ef1fc0f67.png)](http://box.kancloud.cn/2015-09-15_55f7ef1fc0f67.png)
# 2 建立需要的View
不论是为了查询或维护,如果你很常需要使用到同一个查询叙述,你就可以考虑建立一个View元件把这个查询叙述储存起来。下列是建立View元件基本的语法:
[![mysql_11_snap_06](http://box.kancloud.cn/2015-09-15_55f7ef20450b6.png)](http://box.kancloud.cn/2015-09-15_55f7ef20450b6.png)
如果你很常执行查询“每个地区GNP最高的国家”资料,这样的需求可以使用子查询来完成,为了不想要每次重复输入这个查询叙述,你可以建立一个名称“CountryMaxGNP”的View元件,这样以后要执行这个查询的时候就方便多了:
[![mysql_11_snap_07](http://box.kancloud.cn/2015-09-15_55f7ef20b3bd5.png)](http://box.kancloud.cn/2015-09-15_55f7ef20b3bd5.png)
在上列建立View元件的范例中,只有“Name”与“GNP”两个字段,如果想要在已经建立好的“CountryMaxGNP”的View元件中,再加入新的“Code”字段的话:
[![mysql_11_snap_08](http://box.kancloud.cn/2015-09-15_55f7ef213f73e.png)](http://box.kancloud.cn/2015-09-15_55f7ef213f73e.png)
如果需要修改一个已经建立好的View元件,你就要加入“OR REPLACE”的设定,这样才不会出现错误讯息:
[![mysql_11_snap_09](http://box.kancloud.cn/2015-09-15_55f7ef219dade.png)](http://box.kancloud.cn/2015-09-15_55f7ef219dade.png)
如果想要查询一个View元件中会传回哪些字段的资料,可以使用“DESCRIBE”或是比较简短的“DESC”指令:
[![mysql_11_snap_10](http://box.kancloud.cn/2015-09-15_55f7ef226020d.png)](http://box.kancloud.cn/2015-09-15_55f7ef226020d.png)
下列是MySQL关于View元件的规定与限制:
* 在同一个数据库中,View的名称不可以重复,也不可以跟表格名称一样
* View不可以跟Triggers建立联结
储存在View中的查询叙述也有下列的规定:
* 查询叙述中只能使用到已存在的表格或View
* “FROM”子句中不可以使用子查询
* 不可以使用“TEMPORARY”表格
* 不可以使用自行定义的变量、Procedure与Prepared statement参数
注:“TEMPORARY”表格在“表格与索引、建立表格、建立暂存表格”中讨论。“Triggers”、定义变量、“Procedure”与“Prepared statement”在后面都会有章节详细的讨论。
结合查询在关联式数据库中几乎是必要的一种查询,以下列查询“国家与城市人口比例”的需求来说,就需要从“country”与“city”表格中查询必要的字段资料:
[![mysql_11_snap_11](http://box.kancloud.cn/2015-09-15_55f7ef23170df.png)](http://box.kancloud.cn/2015-09-15_55f7ef23170df.png)
如果会经常执行这个结合查询的话,你应该会很希望把它储存为View元件:
[![mysql_11_snap_12](http://box.kancloud.cn/2015-09-15_55f7ef236f346.png)](http://box.kancloud.cn/2015-09-15_55f7ef236f346.png)
你不会在一个表格中,为不同的两个字段取一样的名称;在使用查询叙述提供View元件的字段时,也要注意名称重复的问题,虽然在单纯的结合查询回传的资料中,有一样的字段名称并不会造成错误。要解决这个错误有两种方式,第一种是在查询叙述的“SELECT”子句中,自己为名称重复的字段取不同的字段别名:
[![mysql_11_snap_13](http://box.kancloud.cn/2015-09-15_55f7ef24d83b2.png)](http://box.kancloud.cn/2015-09-15_55f7ef24d83b2.png)
另外一种方式可以在建立View元件的时候,另外指定View元件的字段名称:
[![mysql_11_snap_14](http://box.kancloud.cn/2015-09-15_55f7ef256fd40.png)](http://box.kancloud.cn/2015-09-15_55f7ef256fd40.png)
这样的作法不用修改查询叙述,依照查询叙述回传的字段顺序,另外指定View元件使用的字段名称:
[![mysql_11_snap_15](http://box.kancloud.cn/2015-09-15_55f7ef26c8fc7.png)](http://box.kancloud.cn/2015-09-15_55f7ef26c8fc7.png)
# 3 修改View
使用“ALTER VIEW”叙述,可以让你修改一个已经建立好的View元件:
[![mysql_11_snap_16](http://box.kancloud.cn/2015-09-15_55f7ef275bc06.png)](http://box.kancloud.cn/2015-09-15_55f7ef275bc06.png)
下列的范例使用“ALTER VIEW”叙述修改已经存在的“CountryMaxGNP”View元件:
[![mysql_11_snap_17](http://box.kancloud.cn/2015-09-15_55f7ef279543d.png)](http://box.kancloud.cn/2015-09-15_55f7ef279543d.png)
上列范例执行的工作也可以使用“CREATE OR REPLACE VIEW”叙述来完成:
[![mysql_11_snap_18](http://box.kancloud.cn/2015-09-15_55f7ef323fd0c.png)](http://box.kancloud.cn/2015-09-15_55f7ef323fd0c.png)
如果以修改View元件的工作来说,使用“ALTER VIEW”或“CREATE OR REPLACE VIEW”叙述的效果是完全一样的。唯一的差异是要修改View元件如果不存在的话,“CREATE OR REPLACE VIEW”叙述会直接建立新的View元件:
[![mysql_11_snap_19](http://box.kancloud.cn/2015-09-15_55f7ef3369f6e.png)](http://box.kancloud.cn/2015-09-15_55f7ef3369f6e.png)
# 4 删除View
下列的语法可以删除一个不需要的View元件:
[![mysql_11_snap_20](http://box.kancloud.cn/2015-09-15_55f7ef33f157e.png)](http://box.kancloud.cn/2015-09-15_55f7ef33f157e.png)
如果“DROP VIEW”叙述指定的View元件不存在的话,执行叙述以后会产生错误讯息:
[![mysql_11_snap_21](http://box.kancloud.cn/2015-09-15_55f7ef3455dfa.png)](http://box.kancloud.cn/2015-09-15_55f7ef3455dfa.png)
你可以在“DROP VIEW”叙述加入“IF EXISTS”,这样就可以防止产生View元件不存在的错误讯息:
[![mysql_11_snap_22](http://box.kancloud.cn/2015-09-15_55f7ef349eae7.png)](http://box.kancloud.cn/2015-09-15_55f7ef349eae7.png)
# 5 资料维护与View
View元件除了提供比较方便的查询方式外,你也可以使用View元件来执行资料维护的工作。与View元件应用在查询资料时提供的方便性一样,不使用表格元件,而使用View元件来执行新增、修改或删除的工作,也可以增加资料维护的方便性。
要使用View元件来执行新增、修改或删除的工作,View元件所包含的查询叙述必须符合下列的规则:
* 不可以包含计算或函式的字段
* 只允许一对一的结合查询
* View元件的“ALGORITHM”不可以设定为“TEMPTABLE”
如果符合上列规定的View元件,就会称为“可修改的View元件、updattable views”。只有可修改的View元件,可以使用在“INSERT”、“UPDATE”或“UPDATE”叙述中执行资料维护的工作。
注:View元件的“ALGORITHM”设定在这一章后面的“View的算法”中讨论。
## 5.1 使用View元件执行资料维护
下列是一个可以执行资料维户的View元件,它的字段没有包含计算或函式,也没有使用结合查询:
[![mysql_11_snap_23](http://box.kancloud.cn/2015-09-15_55f7ef3511e1f.png)](http://box.kancloud.cn/2015-09-15_55f7ef3511e1f.png)
如果要修改员工编号“7844”的佣金为600的话,你除了可以在“UPDATE”叙述中指定修改的表格名称为“emp”外,也可以在“UPDATE”叙述中指定View元件“EmpDept30View”:
[![mysql_11_snap_24](http://box.kancloud.cn/2015-09-15_55f7ef3b22e3e.png)](http://box.kancloud.cn/2015-09-15_55f7ef3b22e3e.png)
在执行上列的“UPDATE”叙述以后,不论是查询View元件或表格,都可以确定资料已经修改了:
[![mysql_11_snap_25](http://box.kancloud.cn/2015-09-15_55f7ef3c12633.png)](http://box.kancloud.cn/2015-09-15_55f7ef3c12633.png)
使用“INSERT”叙述新增纪录时,也可以指定View元件“EmpDept30View”:
[![mysql_11_snap_26](http://box.kancloud.cn/2015-09-15_55f7ef3d1d0dc.png)](http://box.kancloud.cn/2015-09-15_55f7ef3d1d0dc.png)
在执行上列的“INSERT”叙述以后,查询View元件所得到的结果并没有刚才新增的员工资料,查询表格时才可以确定资料已经新增,这是因为新增纪录的部门编号字段资料为“NULL”的关系:
[![mysql_11_snap_27](http://box.kancloud.cn/2015-09-15_55f7ef3d7fe29.png)](http://box.kancloud.cn/2015-09-15_55f7ef3d7fe29.png)
与“INSERT”和“UPDATE”叙述一样,“DELETE”叙述也可以指定View元件的纪录资料:
[![mysql_11_snap_49](http://box.kancloud.cn/2015-09-15_55f7ef3ddd807.png)](http://box.kancloud.cn/2015-09-15_55f7ef3ddd807.png)
不过执行上列的删除叙述后,千万不要以为你已经删除员工编号“9001”的员工纪录了:
[![mysql_11_snap_50](http://box.kancloud.cn/2015-09-15_55f7ef3e3772f.png)](http://box.kancloud.cn/2015-09-15_55f7ef3e3772f.png)
## 5.2 使用“WITH CHECK OPTION”
你可以使用View元件来执行资料维护的工作,可是在执行新增或修改的时候,又可能会造成一些有问题的资料。如果你不希望产生这类的问题,你可以为View元件加入“WITH CHECK OPTION”的设定:
[![mysql_11_snap_28](http://box.kancloud.cn/2015-09-15_55f7ef488897b.png)](http://box.kancloud.cn/2015-09-15_55f7ef488897b.png)
加入“WITH CHECK OPTION”设定的View元件,在执行资料维护工作时,会先执行检查的工作,规则是一定要符合“View元件中WHERE设定的条件”:
[![mysql_11_snap_29](http://box.kancloud.cn/2015-09-15_55f7ef4916b08.png)](http://box.kancloud.cn/2015-09-15_55f7ef4916b08.png)
因为上列范例所新增的纪录资料,“deptno”字段会储存“NULL”值,这样就违反View元件中“WHERE deptno = 30”的条件设定了,所以在执行以后会产生错误讯息。下列的修改叙述就可以正确的执行:
[![mysql_11_snap_30](http://box.kancloud.cn/2015-09-15_55f7ef4e666dd.png)](http://box.kancloud.cn/2015-09-15_55f7ef4e666dd.png)
View元件中的“WITH CHECK OPTION”设定,还有额外的“CASCADE”和“LOCAL”两个控制检查范围的设定:
[![mysql_11_snap_31](http://box.kancloud.cn/2015-09-15_55f7ef4ea1f07.png)](http://box.kancloud.cn/2015-09-15_55f7ef4ea1f07.png)
会有“CASCADE”和“LOCAL”这两个设定的原因,是因为View元件的资料来源可以一个表格,也可以是一个View元件:
[![mysql_11_snap_32](http://box.kancloud.cn/2015-09-15_55f7ef4f1df77.png)](http://box.kancloud.cn/2015-09-15_55f7ef4f1df77.png)
查询“EmpDept20View”后,传回的纪录资料包含“deptno = 20”条件,与设定在“EmpSalaryView”的“salary >= 1500”条件:
[![mysql_11_snap_33](http://box.kancloud.cn/2015-09-15_55f7ef4fb798e.png)](http://box.kancloud.cn/2015-09-15_55f7ef4fb798e.png)
检查范围设定为“LOCAL”的View元件,在执行资料维护的时候,只会检查是否符合自己的条件设定:
[![mysql_11_snap_34](http://box.kancloud.cn/2015-09-15_55f7ef501e60c.png)](http://box.kancloud.cn/2015-09-15_55f7ef501e60c.png)
如果执行资料维护的叙述违反“EmpSalaryView”的条件设定,还是可以正确的执行:
[![mysql_11_snap_35](http://box.kancloud.cn/2015-09-15_55f7ef506742c.png)](http://box.kancloud.cn/2015-09-15_55f7ef506742c.png)
如果你希望所有的View元件在执行资料维护的时候,都不可以出现这类的问题,就应该把View元件的检查范围设定为“CASCADE”:
[![mysql_11_snap_36](http://box.kancloud.cn/2015-09-15_55f7ef55c1bbb.png)](http://box.kancloud.cn/2015-09-15_55f7ef55c1bbb.png)
检查范围设定为“CASCADE”的View元件,在执行资料维护的时候,就不能违反所有VIew元件的条件设定:
[![mysql_11_snap_37](http://box.kancloud.cn/2015-09-15_55f7ef56699f7.png)](http://box.kancloud.cn/2015-09-15_55f7ef56699f7.png)
# 6 View的算法
View元件可以提供更方便的资料查询与维护方式,在你建立View元件的时候,除了指定的查询叙述要符合规定,还可以指定数据库执行View元件时所使用的“算法、algorithm”:
[![mysql_11_snap_38](http://box.kancloud.cn/2015-09-15_55f7ef56e6d76.png)](http://box.kancloud.cn/2015-09-15_55f7ef56e6d76.png)
一般来说,你不需要特别指定View元件使用的算法。如果在建立View元件的时候,没有指定使用的算法为“MERGE”或“TEMPTABLE”,MySQL会设定为“UNDEFINED”,这个设定表示MySQL会依照View元件中包含的叙述,自动选择一个适合的算法,可能是“MERGE”或“TEMPTABLE”。
下列是一个算法设定为“MERGE”的View元件,在MySQL数据库中的运作情形:
[![mysql_11_snap_39](http://box.kancloud.cn/2015-09-15_55f7ef57c2874.png)](http://box.kancloud.cn/2015-09-15_55f7ef57c2874.png)
下列是一个算法设定为“TEMPTABLE”的View元件,在MySQL数据库中的运作情形:
[![mysql_11_snap_40](http://box.kancloud.cn/2015-09-15_55f7ef586f8cb.png)](http://box.kancloud.cn/2015-09-15_55f7ef586f8cb.png)
并不是所有的View元件都可以指定算法设定为“MERGE”,以下列查询员工统计资讯的叙述来说:
[![mysql_11_snap_41](http://box.kancloud.cn/2015-09-15_55f7ef5941dae.png)](http://box.kancloud.cn/2015-09-15_55f7ef5941dae.png)
如果执行下列建立View元件的叙述,就会产生警告的讯息:
[![mysql_11_snap_42](http://box.kancloud.cn/2015-09-15_55f7ef59a520c.png)](http://box.kancloud.cn/2015-09-15_55f7ef59a520c.png)
如果View元件包含的查询叙述有下列的情况,MySQL都会自动把算法设定为“UNDEFINED”:
* 群组函式:SUM()、MIN()、MAX()、COUNT()
* DISTINCT
* GROUP BY
* HAVING
* UNION或UNION ALL
* “SELECT”子句中包含一个明确的值,而不是表格的字段
# 7 View的维护与资讯
## 7.1 检验View的正确性
在你建立一个View元件的时候,MySQL会检查View元件包含的查询叙述是否正确,如果没有问题的话,才会储存View元件的设定。不过以下列的范例来说:
[![mysql_11_snap_43](http://box.kancloud.cn/2015-09-15_55f7ef5eea03e.png)](http://box.kancloud.cn/2015-09-15_55f7ef5eea03e.png)
如果不小心删除“EmpSalaryView”这个View元件:
[![mysql_11_snap_44](http://box.kancloud.cn/2015-09-15_55f7ef5fb6973.png)](http://box.kancloud.cn/2015-09-15_55f7ef5fb6973.png)
执行查询“EmpDept20View”的时候,就会产生警告讯息了:
[![mysql_11_snap_45](http://box.kancloud.cn/2015-09-15_55f7ef61161fb.png)](http://box.kancloud.cn/2015-09-15_55f7ef61161fb.png)
这样的问题也可以经由使用检查表格或View元件的叙述发现:
[![mysql_11_snap_46](http://box.kancloud.cn/2015-09-15_55f7ef618d305.png)](http://box.kancloud.cn/2015-09-15_55f7ef618d305.png)
执行检查“EmpDept20View”的叙述可以发现这是一个有问题的View元件:
[![mysql_11_snap_47](http://box.kancloud.cn/2015-09-15_55f7ef61cbb32.png)](http://box.kancloud.cn/2015-09-15_55f7ef61cbb32.png)
## 7.2 取得View的相关资讯
MySQL数据库在启动以后,会有一个很特别的数据库,名称是“information_schema”,这个数据库通常会称为“系统资讯数据库”。这个数据库中有一个表格叫作“VIEWS”,它储存所有MySQL数据库中View元件的相关资讯,“VIEWS”表格有下列主要的字段:
| 字段名称 | 型态 | 说明 |
| --- | --- | --- |
| TABLE_SCHEMA | varchar(64) | 数据库名称 |
| TABLE_NAME | varchar(64) | 表格名称 |
| VIEW_DEFINITION | longtext | 算法定义与储存的查询叙述 |
| CHECK_OPTION | varchar(8) | 检查范围设定 |
| IS_UPDATABLE | varchar(3) | 是否可以执行资料维护 |
执行下列的叙述就可以查询数据库中的View元件资讯:
[![mysql_11_snap_48](http://box.kancloud.cn/2015-09-15_55f7ef674bcf8.png)](http://box.kancloud.cn/2015-09-15_55f7ef674bcf8.png)
';