最近在实习的项目中用到了视图,所以初步学习一下视图。
视图的基本操作
视图基本概述:
视图是一个虚拟表(物理上并不存在),其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集,并可以将其当作表来使用,同真实的表一样,视图包含一系列带有名称的列和行数据,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图时动态生成。视图本质上是存储在数据库中的查询的sql 语句,一方面是安全起见,可以隐藏一些数据,另外一方面是可以便于使用和理解复杂查询。
创建视图
CREATE VIEW view_name AS
SELECT column_name(s)
FROM table_name
WHERE condition
example:
根据chatbot_interaction_faq表chatbot_interaction_domain表中的内容建立视图v_faq_domain_question
CREATE VIEW v_faq_domain_question AS SELECT
question,
appid
FROM
( SELECT question, appid FROM chatbot_interaction_faq WHERE STATUS = 1 UNION ALL SELECT question, appid FROM chatbot_interaction_domain WHERE STATUS = 1 ) a
GROUP BY
a.question
WITH CHECK OPTION;
上面的语句中,v_faq_domain_question为视图名称,下面的子查询根据筛选条件拼接了两个表中的appid和question
其中,WITH CHECK OPTION在定义视图时使用,是为了保证视图一致性,表示任何通过视图更新的行,都必须符合视图本身的WHERE条件定义,不能更新视图定义的列以外的列。
查询时,直接像查询表一样使用即可:
SELECT
question
FROM
v_faq_domain_question
WHERE
question LIKE CONCAT('%',"新闻",'%' )
AND appid = "thecover" LIMIT 4
当创建视图后,可以使用DESC + 视图名称查看视图:
修改视图(修改视图结构)
修改视图:是指修改数据库中,存在的视图的定义比如,当基本表中的某些字段发生变化时,可以通过修改视图的方式,来保持视图与基本表的一致性
修改视图有两种方式:
- 使用CREATE OR REPLACE VIEW
用这种方式修改视图时,如果修改的视图存在,就会使用修改语句修改视图,如果不存在,那么将会创建一个新的视图。
CREATE [OR REPLACE] [ALGORITHM={UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS SELECT_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]]
example:
CREATE OR REPLACE VIEW v_faq_domain_question AS SELECT * FROM chatbot_interaction_faq;
- 使用ALTER
ALTER [ALGORITHM={UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS SELECT_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
example:
ALTER VIEW v_faq_domain_question AS SELECT question FROM chatbot_interaction_faq;
更新视图
MySQL支持可更新视图,可更新视图是指可以通过更新视图来更新视图涉及的相关表,只要指定了合适的条件,就可以更新,删除,或者像视图中写入数据,如下:
UPDATE v_faq_domain_question SET question = CONCAT('faq_',question);
但是如果视图定义包含了GROUP BY, UNION, 聚合函数,以及其它一些特殊情况,就不能对视图进行更新了。
补充:某些关系型数据库允许在视图上建立触发器,通过触发器可以精确控制在修改视图数据时做些什么,但是注意MySQL不支持在视图上建立任何触发器
删除视图
DROP VIEW view_name
example:
DROP VIEW v_faq_domain_question
注意:视图本质上不是表,不能使用DROP TABLE来删除视图
MySQL处理视图的两种算法
首先需要知道MySQL处理视图的两种算法:MERGE(合并算法)和TEMPTABLE(临时表算法)
下图源于《高性能MySQL》中对这两个算法的流程解读
- 合并算法
MERGE是指在处理涉及到视图的操作时,将对视图的操作根据视图的定义进行展开
修改视图SQL:
ALTER VIEW v_faq_domain_question AS SELECT question FROM chatbot_interaction_faq;
select_type为SIMPLE,可见,使用的是MERGE算法
2. 临时表算法
一般来说在能够使用MERGE算法的时候MySQL处理视图上没什么性能问题,但并非在任何时候都能使用MERGE算法。只要视图的定义稍稍有点复杂,MySQL就不能使用MERGE算法了 。也就是说,只要视图定义中使用了以下SQL构造块 就无法使用MERGE算法:
- 聚合函数
- DISTINCT
- GROUP BY
- HAVING
- 集合操作(在MySQL中只有UNION, UNION ALL,没有EXCEPT和INTERSECT)
- 子查询
可以看到,当我使用了集合操作时,其中select_type为DERIVED,也就是临时表算法
创建视图SQL:
CREATE VIEW v_faq_domain_question AS SELECT
question,
appid
FROM
( SELECT question, appid FROM chatbot_interaction_faq WHERE STATUS = 1 UNION ALL SELECT question, appid FROM chatbot_interaction_domain WHERE STATUS = 1 ) a
GROUP BY
a.question
WITH CHECK OPTION;
具体的式例可以参见这篇博客或者官方的文档来辅助理解:http://wangyuanzju.blog.163.com/blog/static/130292007714102859807/
限制
在有的一些关系型数据库中,可以物化视图,但是MySQL并不支持物化视图
物化视图:指的是将视图结果数据存放在一个可以查看的表中,并定期从原始表中刷新数据到这个表中
同时MySQL也不支持在视图中创建索引。
初次之外,还有一些限制,比如MySQL并不会保存视图定义的原始SQL语句,可以通过SHOW CREATE VIEW来显示创建语句,但会有一些不同,需要自己进行一些处理