目錄mysql
22.1. ALTER VIEW語法算法
22.2. CREATE VIEW語法sql
22.3. DROP VIEW語法數據庫
22.4. SHOW CREATE VIEW語法函數
本章討論了下述主題:測試
· 使用CREATE VIEW或ALTER VIEW建立或更改視圖。spa
· 使用DROP VIEW銷燬視圖。code
· 使用SHOW CREATE VIEW顯示視圖元數據。對象
若是你已從不支持視圖的較舊版本升級到MySQL 5.1,要想使用視圖,應升級受權表,使之包含與視圖有關的權限。blog
22.1. ALTER VIEW語法
ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
該語句用於更改已有視圖的定義。其語法與CREATE VIEW相似。該語句須要具備針對視圖的CREATE VIEW和DROP權限,也須要針對SELECT語句中引用的每一列的某些權限。
22.2. CREATE VIEW語法
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
該語句能建立新的視圖,若是給定了OR REPLACE子句,該語句還能替換已有的視圖。select_statement是一種SELECT語句,它給出了視圖的定義。該語句可從基表或其餘視圖進行選擇。
該語句要求具備針對視圖的CREATE VIEW權限,以及針對由SELECT語句選擇的每一列上的某些權限。對於在SELECT語句中其餘地方使用的列,必須具備SELECT權限。若是還有OR REPLACE子句,必須在視圖上具備DROP權限。
視圖屬於數據庫。在默認狀況下,將在當前數據庫建立新視圖。要想在給定數據庫中明確建立視圖,建立時,應將名稱指定爲db_name.view_name。
mysql> CREATE VIEW test.v AS SELECT * FROM t;
表和視圖共享數據庫中相同的名稱空間,所以,數據庫不能包含具備相同名稱的表和視圖。
視圖必須具備惟一的列名,不得有重複,就像基表那樣。默認狀況下,由SELECT語句檢索的列名將用做視圖列名。要想爲視圖列定義明確的名稱,可以使用可選的column_list子句,列出由逗號隔開的ID。column_list中的名稱數目必須等於SELECT語句檢索的列數。
SELECT語句檢索的列能夠是對錶列的簡單引用。也能夠是使用函數、常量值、操做符等的表達式。
對於SELECT語句中不合格的表或視圖,將根據默認的數據庫進行解釋。經過用恰當的數據庫名稱限定表或視圖名,視圖可以引用表或其餘數據庫中的視圖。
可以使用多種SELECT語句建立視圖。視圖可以引用基表或其餘視圖。它能使用聯合、UNION和子查詢。SELECT甚至不需引用任何表。在下面的示例中,定義了從另外一表選擇兩列的視圖,並給出了根據這些列計算的表達式:
mysql> CREATE TABLE t (qty INT, price INT); mysql> INSERT INTO t VALUES(3, 50); mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t; mysql> SELECT * FROM v; +------+-------+-------+ | qty | price | value | +------+-------+-------+ | 3 | 50 | 150 | +------+-------+-------+
視圖定義服從下述限制:
· SELECT語句不能包含FROM子句中的子查詢。
· SELECT語句不能引用系統或用戶變量。
· SELECT語句不能引用預處理語句參數。
· 在存儲子程序內,定義不能引用子程序參數或局部變量。
· 在定義中引用的表或視圖必須存在。可是,建立了視圖後,可以捨棄定義引用的表或視圖。要想檢查視圖定義是否存在這類問題,可以使用CHECK TABLE語句。
· 在定義中不能引用TEMPORARY表,不能建立TEMPORARY視圖。
· 在視圖定義中命名的表必須已存在。
· 不能將觸發程序與視圖關聯在一塊兒。
在視圖定義中容許使用ORDER BY,可是,若是從特定視圖進行了選擇,而該視圖使用了具備本身ORDER BY的語句,它將被忽略。
對於定義中的其餘選項或子句,它們將被增長到引用視圖的語句的選項或子句中,但效果未定義。例如,若是在視圖定義中包含LIMIT子句,並且從特定視圖進行了選擇,而該視圖使用了具備本身LIMIT子句的語句,那麼對使用哪一個LIMIT未做定義。相同的原理也適用於其餘選項,如跟在SELECT關鍵字後的ALL、DISTINCT或SQL_SMALL_RESULT,並適用於其餘子句,如INTO、FOR UPDATE、LOCK IN SHARE MODE、以及PROCEDURE。
若是建立了視圖,並經過更改系統變量更改了查詢處理環境,會影響從視圖得到的結果:
mysql> CREATE VIEW v AS SELECT CHARSET(CHAR(65)), COLLATION(CHAR(65)); Query OK, 0 rows affected (0.00 sec) mysql> SET NAMES 'latin1'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM v; +-------------------+---------------------+ | CHARSET(CHAR(65)) | COLLATION(CHAR(65)) | +-------------------+---------------------+ | latin1 | latin1_swedish_ci | +-------------------+---------------------+ 1 row in set (0.00 sec) mysql> SET NAMES 'utf8'; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM v; +-------------------+---------------------+ | CHARSET(CHAR(65)) | COLLATION(CHAR(65)) | +-------------------+---------------------+ | utf8 | utf8_general_ci | +-------------------+---------------------+ 1 row in set (0.00 sec)
可選的ALGORITHM子句是對標準SQL的MySQL擴展。ALGORITHM可取三個值:MERGE、TEMPTABLE或UNDEFINED。若是沒有ALGORITHM子句,默認算法是UNDEFINED(未定義的)。算法會影響MySQL處理視圖的方式。
對於MERGE,會將引用視圖的語句的文本與視圖定義合併起來,使得視圖定義的某一部分取代語句的對應部分。
對於TEMPTABLE,視圖的結果將被置於臨時表中,而後使用它執行語句。
對於UNDEFINED,MySQL將選擇所要使用的算法。若是可能,它傾向於MERGE而不是TEMPTABLE,這是由於MERGE一般更有效,並且若是使用了臨時表,視圖是不可更新的。
明確選擇TEMPTABLE的1個緣由在於,建立臨時表以後、並在完成語句處理以前,可以釋放基表上的鎖定。與MERGE算法相比,鎖定釋放的速度更快,這樣,使用視圖的其餘客戶端不會被屏蔽過長時間。
視圖算法能夠是UNDEFINED,有三種方式:
· 在CREATE VIEW語句中沒有ALGORITHM子句。
· CREATE VIEW語句有1個顯式ALGORITHM = UNDEFINED子句。
· 爲僅能用臨時表處理的視圖指定ALGORITHM = MERGE。在這種狀況下,MySQL將生成告警,並將算法設置爲UNDEFINED。
正如前面所介紹的那樣,經過將視圖定義中的對應部分合併到引用視圖的語句中,對MERGE進行處理。在下面的示例中,簡要介紹了MERGE的工做方式。在該示例中,假定有1個具備下述定義的視圖v_merge:
CREATE ALGORITHM = MERGE VIEW v_merge (vc1, vc2) AS
SELECT c1, c2 FROM t WHERE c3 > 100;
示例1:假定發出了下述語句:
SELECT * FROM v_merge;
MySQL如下述方式處理語句:
· v_merge成爲t
· *成爲vc一、vc2,與c一、c2對應
· 增長視圖WHERE子句
所產生的將執行的語句爲:
SELECT c1, c2 FROM t WHERE c3 > 100;
示例2:假定發出了下述語句:
SELECT * FROM v_merge WHERE vc1 < 100;
該語句的處理方式與前面介紹的相似,但vc1 < 100變爲c1 < 100,並使用AND鏈接詞將視圖的WHERE子句添加到語句的WHERE子句中(增長了圓括號以確保以正確的優先順序執行子句部分)。所得的將要執行的語句變爲:
SELECT c1, c2 FROM t WHERE (c3 > 100) AND (c1 < 100);
事實上,將要執行的語句是具備下述形式的WHERE子句:
WHERE (select WHERE) AND (view WHERE)
MERGE算法要求視圖中的行和基表中的行具備一對一的關係。若是不具備該關係。必須使用臨時表取而代之。若是視圖包含下述結構中的任何一種,將失去一對一的關係:
· 聚合函數(SUM(), MIN(), MAX(), COUNT()等)。
· DISTINCT
· GROUP BY
· HAVING
· UNION或UNION ALL
· 僅引用文字值(在該狀況下,沒有基本表)。
某些視圖是可更新的。也就是說,能夠在諸如UPDATE、DELETE或INSERT等語句中使用它們,以更新基表的內容。對於可更新的視圖,在視圖中的行和基表中的行之間必須具備一對一的關係。還有一些特定的其餘結構,這類結構會使得視圖不可更新。更具體地講,若是視圖包含下述結構中的任何一種,那麼它就是不可更新的:
· 聚合函數(SUM(), MIN(), MAX(), COUNT()等)。
· DISTINCT
· GROUP BY
· HAVING
· UNION或UNION ALL
· 位於選擇列表中的子查詢
· Join
· FROM子句中的不可更新視圖
· WHERE子句中的子查詢,引用FROM子句中的表。
· 僅引用文字值(在該狀況下,沒有要更新的基本表)。
· ALGORITHM = TEMPTABLE(使用臨時表總會使視圖成爲不可更新的)。
關於可插入性(可用INSERT語句更新),若是它也知足關於視圖列的下述額外要求,可更新的視圖也是可插入的:
· 不得有重複的視圖列名稱。
· 視圖必須包含沒有默認值的基表中的全部列。
· 視圖列必須是簡單的列引用而不是導出列。導出列不是簡單的列引用,而是從表達式導出的。下面給出了一些導出列示例:
· 3.14159
· col1 + 3
· UPPER(col2)
· col3 / col4
· (subquery)
混合了簡單列引用和導出列的視圖是不可插入的,可是,若是僅更新非導出列,視圖是可更新的。考慮下述視圖:
CREATE VIEW v AS SELECT col1, 1 AS col2 FROM t;
該視圖是不可插入的,這是由於col2是從表達式導出的。可是,若是更新時不更新col2,它是可更新的。這類更新是容許的:
UPDATE v SET col1 = 0;
下述更新是不容許的,緣由在於,它試圖更新導出列:
UPDATE v SET col2 = 0;
在某些狀況下,可以更新多表視圖,假定它能使用MERGE算法進行處理。爲此,視圖必須使用內部聯合(而不是外部聯合或UNION)。此外,僅能更新視圖定義中的單個表,所以,SET子句必須僅命名視圖中某一表的列。即便從理論上講也是可更新的,不容許使用UNION ALL的視圖,這是由於,在實施中將使用臨時表來處理它們。
對於多表可更新視圖,若是是將其插入單個表中,INSERT可以工做。不支持DELETE。
對於可更新視圖,可給定WITH CHECK OPTION子句來防止插入或更新行,除非做用在行上的select_statement中的WHERE子句爲「真」。
在關於可更新視圖的WITH CHECK OPTION子句中,當視圖是根據另外一個視圖定義的時,LOCAL和CASCADED關鍵字決定了檢查測試的範圍。LOCAL關鍵字對CHECK OPTION進行了限制,使其僅做用在定義的視圖上,CASCADED會對將進行評估的基表進行檢查。若是未給定任一關鍵字,默認值爲CASCADED。請考慮下述表和視圖集合的定義:
mysql> CREATE TABLE t1 (a INT); mysql> CREATE VIEW v1 AS SELECT * FROM t1 WHERE a < 2 -> WITH CHECK OPTION; mysql> CREATE VIEW v2 AS SELECT * FROM v1 WHERE a > 0 -> WITH LOCAL CHECK OPTION; mysql> CREATE VIEW v3 AS SELECT * FROM v1 WHERE a > 0 -> WITH CASCADED CHECK OPTION;
這裏,視圖v2和v3是根據另外一視圖v1定義的。v2具備LOCAL檢查選項,所以,僅會針對v2檢查對插入項進行測試。v3具備CASCADED檢查選項,所以,不只會針對它本身的檢查對插入項進行測試,也會針對基本視圖的檢查對插入項進行測試。在下面的語句中,介紹了這些差別:
mysql> INSERT INTO v2 VALUES (2); Query OK, 1 row affected (0.00 sec) mysql> INSERT INTO v3 VALUES (2); ERROR 1369 (HY000): CHECK OPTION failed 'test.v3'
視圖的可更新性可能會受到系統變量updatable_views_with_limit的值的影響。
INFORMATION_SCHEMA包含1個VIEWS表,從該表可獲取關於視圖對象的信息。
22.3. DROP VIEW語法
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
DROP VIEW可以刪除1個或多個視圖。必須在每一個視圖上擁有DROP權限。
可使用關鍵字IF EXISTS來防止因不存在的視圖而出錯。給定了該子句時,將爲每一個不存在的視圖生成NOTE。若是給定了RESTRICT和CASCADE,將解析並忽略它們。
22.4. SHOW CREATE VIEW語法
SHOW CREATE VIEW view_name
該語句給出了1個建立給定視圖的CREATE VIEW語句。
mysql> SHOW CREATE VIEW v;
+------+----------------------------------------------------+
| View | Create View |
+------+----------------------------------------------------+
| v | CREATE VIEW `test`.`v` AS select 1 AS `a`,2 AS `b` |
+------+----------------------------------------------------+