最近在實習的項目中用到了視圖,所以初步學習一下視圖。
視圖的基本操作
視圖基本概述:
視圖是一個虛擬表(物理上並不存在),其本質是根據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來顯示創建語句,但會有一些不同,需要自己進行一些處理