概念
MySQL
不支持物化视图,MySQL
的视图是一个虚拟表,在引用视图时动态生成,与其对应的数据并不会像表一样在数据库中再存储一份
创建视图
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = <用户名>@<主机名>]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW <视图名称> [(<视图的属性列表>)]
AS <SELECT 语句>
[WITH {CASCADED | LOCAL} CHECK OPTION]
CREATE
表示创建视图,OR REPLACE
表示如果视图已存在则替换已存在的视图ALGORITHM
指定算法UNDEFINED
自动选择MERGE
将视图sql合并到主查询sql中,重新构成新sql进行查询。TEMPTABLE
将视图的结果存入临时表,用临时表执行语句
DEFINER
表示创建者SQL SECURITY {DEFINER | INVOKER}
表示安全性,指定执行权限。DEFINER
只有创建者有权执行,INVOKER
有权限的调用者可以执行可以不指定属性列表,而使用 SELECT 语句查询的列作为视图的列名
WITH [CASCADED | LOCAL] CHECK OPTION
视图在更新数据时,需要保证更新后的数据仍在视图的权限范围之内(更新后的数据通过 SELECT 视图 可以查看)CASCADE
是默认值,表示更新视图数据时,要满足所有相关视图和表的条件。因为MySQL
允许基于另一个视图创建视图,它还会检查依赖视图中的规则以保持一致性。LOCAL
表示更新视图数据时满足该视图本身定义的条件即可
修改视图
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = <用户名>@<主机名>]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW <视图名称> [(<视图的属性列表>)]
AS <SELECT 语句>
[WITH {CASCADED | LOCAL} CHECK OPTION]
与创建语句非常类似
删除视图
DROP VIEW [IF EXISTS] <视图名称>[,<视图名称>...]
查看视图
SHOW TABLE STATUS [LIKE '<关键字>']
SHOW CREATE VIEW <视图名称>
DESCRIBE <视图名称>
视图的优点
简化 SQL,提高开发效率
视图不仅可以简化用户对数据的理解,也可以简化他们的操作,对于经常使用的查询,可以定义为视图,如:
数据库设计范式要求我们减少冗余字段,因此现在很多数据表都没有计算列字段,如采购单:有价格、数量、税率、含税金额,多半没有不含税金额、税额,而这些字段在很多报表中有都会用到,所以我们可以创建一个含有计算列字段的视图来解决这个问题
不同表字段聚合,信息重组,如:经销商通常有业务员,业务员通常有上下级关系(客户经理、区域经理、大区经理等),因此查看经销商业务员时我们需要看到直管业务员是谁?该业务员对应的区域经理、大区经理是谁(可能NULL)?因此我们可以联合经销商表、业务员信息表、业务员上下级关系表定义一个经销商视图
安全性
通过视图用户只能查询和修改他们能看到的数据。数据库授权命令可以使用户对数据库的检索限制到特定的数据库对象上,而不能精确到具体的行或列。通过视图,用户的权限可以被限制在数据的不同子集上。如:
- 需要xx系统数据,又没接口,怎么办?直接操作数据库,这时就涉及数据安全性,合理利用视图则可以减少很多授权工作和保证数据安全性。当下新构建的系统几乎都是暴露api接口,因此数据安全性更多关注在接口的身份认证和数据粒度方面。
逻辑数据独立性
使用视图,可以屏蔽真实表结构的变化带来的影响
视图性能
MySQL
在处理视图时有两种算法,分别称为 MERGE
和 TEMPTABLE
。
在创建视图时可以指定使用哪种算法。不显式指定的话,MySQL
默认使用 Merge
算法。
MERGE
,将视图sql合并到主查询sql中,重新构成新sql进行查询。
TEMPTABLE
,就是将视图当做临时表来处理。
一般来说在能够使用 MERGE
算法的时候处理视图没什么性能问题,因为可以使用索引、查询优化算法,但并非在任何时候都能使用 MERGE
算法。事实上,只要视图的定义稍稍有点复杂,MySQL
就没办法使用 MERGE
算法了。准确的说,只要视图定义中使用了以下 SQL
构造块就无法使用 MERGE
算法:
聚集函数
DISTINCT
GROUP BY
HAVING
集合操作(UNION, UNION ALL)
子查询
对于复杂视图定义,MySQL
使用了一种以不变应万变的方法,即先执行视图定义,将其结果使用临时表保存起来,这样后续对视图的操作就转化为对临时表的操作。不能不说从单从软件设计的角度看,这样的方法非常的优雅,然而从性能角度,这一方法也是非常的差。
所以尽量让视图采用 MERGE
算法,视图定义中避免 DISTINCT、GROUP BY
等集合相关的运算;如果视图很复杂必须采用 TEMPTABLE
的话,也要想办法减少记录数。