CREATE
[OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name [(column_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION]
CREATE VIEW
陳述式會建立新的檢視表,如果指定了 OR REPLACE
子句,則會取代現有的檢視表。如果檢視表不存在,CREATE OR REPLACE VIEW
與 CREATE VIEW
相同。如果檢視表存在,CREATE OR REPLACE VIEW
會取代它。
關於檢視表使用限制的資訊,請參閱 第 27.10 節「檢視表的限制」。
select_statement
是一個 SELECT
陳述式,提供檢視表的定義。(從檢視表選取,實際上是使用 SELECT
陳述式。)select_statement
可以從基本表格或其他檢視表選取。如同 CREATE TABLE ... SELECT
,SELECT
陳述式可以使用 VALUES
陳述式作為其來源,或可以用 TABLE
陳述式取代。
檢視表定義在建立時會 「凍結」,且不受基礎表格定義後續變更的影響。例如,如果檢視表定義為表格上的 SELECT *
,稍後加入表格的新欄不會成為檢視表的一部分,而從表格中刪除的欄在從檢視表選取時會導致錯誤。
ALGORITHM
子句會影響 MySQL 處理檢視表的方式。DEFINER
和 SQL SECURITY
子句指定在檢視表叫用時檢查存取權限時要使用的安全內容。WITH CHECK OPTION
子句可以用於限制對檢視表參考之表格中資料列的插入或更新。這些子句將在本節稍後說明。
CREATE VIEW
陳述式需要檢視表的 CREATE VIEW
權限,以及 SELECT
陳述式選取之每個欄的某些權限。對於 SELECT
陳述式中其他地方使用的欄,您必須具有 SELECT
權限。如果存在 OR REPLACE
子句,您也必須具有檢視表的 DROP
權限。如果存在 DEFINER
子句,所需的權限取決於 user
值,如 第 27.7 節「儲存物件的存取控制」中所述。
當參考檢視表時,會依照本節稍後所述進行權限檢查。
檢視表屬於資料庫。預設情況下,新的檢視表會建立在預設資料庫中。若要在指定的資料庫中明確建立檢視表,請使用 db_name.view_name
語法,以資料庫名稱限定檢視表名稱。
CREATE VIEW test.v AS SELECT * FROM t;
SELECT
陳述式中未限定的表格或檢視表名稱,也會根據預設資料庫進行解譯。檢視表可以透過使用適當的資料庫名稱限定表格或檢視表名稱,來參考其他資料庫中的表格或檢視表。
在資料庫內,基本表格和檢視表共用相同的命名空間,因此基本表格和檢視表不能具有相同的名稱。
SELECT
陳述式擷取的欄可以是表格欄的簡單參考,或使用函數、常數值、運算子等的運算式。
檢視表必須具有唯一的欄名稱,且沒有重複項目,就像基本表格一樣。預設情況下,SELECT
陳述式擷取的欄名稱會用於檢視表欄名稱。若要定義檢視表欄的明確名稱,請指定選用的 column_list
子句作為逗號分隔的識別碼清單。column_list
中的名稱數量必須與 SELECT
陳述式擷取的欄數量相同。
可以從許多種類的 SELECT
陳述式建立檢視表。它可以參考基本表格或其他檢視表。它可以使用聯結、UNION
和子查詢。SELECT
甚至不需要參考任何表格。
CREATE VIEW v_today (today) AS SELECT CURRENT_DATE;
以下範例定義一個檢視表,從另一個表格中選取兩個欄,以及從這些欄計算的運算式。
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
陳述式不能參考系統變數或使用者定義的變數。在儲存的程式中,
SELECT
陳述式不能參考程式參數或區域變數。SELECT
陳述式不能參考預先處理的陳述式參數。定義中參考的任何表格或檢視表都必須存在。如果建立檢視表後,定義所參考的表格或檢視表被刪除,使用檢視表會導致錯誤。若要檢查此類問題的檢視表定義,請使用
CHECK TABLE
陳述式。定義不能參考
TEMPORARY
表格,且您不能建立TEMPORARY
檢視表。您無法將觸發程序與檢視表相關聯。
SELECT
陳述式中欄名稱的別名會針對 64 個字元的最大欄長度進行檢查(而非 256 個字元的最大別名長度)。
在檢視表定義中允許 ORDER BY
,但如果您使用具有自己的 ORDER BY
的陳述式從檢視表選取,則會忽略它。
對於定義中的其他選項或子句,會將其新增至參考檢視表之陳述式的選項或子句,但效果未定義。例如,如果檢視表定義包含 LIMIT
子句,且您使用具有自己的 LIMIT
子句的陳述式從檢視表選取,則未定義哪一個限制會套用。相同的原則適用於 SELECT
關鍵字之後的選項,例如 ALL
、DISTINCT
或 SQL_SMALL_RESULT
,以及諸如 INTO
、FOR UPDATE
、FOR SHARE
、LOCK IN SHARE MODE
和 PROCEDURE
等子句。
如果您透過變更系統變數來變更查詢處理環境,從檢視表取得的結果可能會受到影響。
mysql> CREATE VIEW v (mycol) AS SELECT 'abc';
Query OK, 0 rows affected (0.01 sec)
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| mycol |
+-------+
1 row in set (0.01 sec)
mysql> SET sql_mode = 'ANSI_QUOTES';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT "mycol" FROM v;
+-------+
| mycol |
+-------+
| abc |
+-------+
1 row in set (0.00 sec)
當執行參考檢視表的陳述式時,DEFINER
和 SQL SECURITY
子句會決定在檢查檢視表的存取權限時要使用的 MySQL 帳戶。有效的 SQL SECURITY
特徵值為 DEFINER
(預設值)和 INVOKER
。這些值分別表示必要的權限必須由定義或叫用檢視表的使用者持有。
如果存在 DEFINER
子句,則 user
值應為指定為 '
、user_name
'@'host_name
'CURRENT_USER
或 CURRENT_USER()
的 MySQL 帳戶。允許的 user
值取決於您擁有的權限,如 第 27.7 節「儲存物件的存取控制」中所述。另請參閱該節以取得有關檢視表安全性的其他資訊。
如果省略 DEFINER
子句,預設定義者是執行 CREATE VIEW
陳述式的使用者。這與明確指定 DEFINER = CURRENT_USER
相同。
在檢視表定義中,預設情況下,CURRENT_USER
函數會傳回檢視表的 DEFINER
值。對於使用 SQL SECURITY INVOKER
特徵定義的檢視表,CURRENT_USER
會傳回檢視表叫用者的帳戶。如需檢視表內使用者稽核的相關資訊,請參閱 第 8.2.23 節「以 SQL 為基礎的帳戶活動稽核」。
在使用 SQL SECURITY DEFINER
特徵定義的儲存常式中,CURRENT_USER
會傳回常式的 DEFINER
值。這也會影響在此類常式內定義的檢視表,如果檢視表定義包含 CURRENT_USER
的 DEFINER
值。
MySQL 會這樣檢查檢視表權限:
在檢視定義時,檢視建立者必須擁有使用檢視所存取的最上層物件所需的權限。例如,如果檢視定義引用了資料表欄位,建立者必須對定義的選取清單中的每個欄位都具有某些權限,並且對定義中其他地方使用的每個欄位都具有
SELECT
權限。如果定義引用了預存函式,則只能檢查呼叫該函式所需的權限。函式呼叫時所需的權限只能在執行時檢查:對於不同的呼叫,可能會執行函式內的不同執行路徑。當引用檢視時,針對檢視所存取的物件的權限會根據檢視的
DEFINER
帳戶或調用者所擁有的權限進行檢查,具體取決於SQL SECURITY
特性是DEFINER
還是INVOKER
。如果引用檢視導致預存函式的執行,則函式內執行的語句的權限檢查取決於函式的
SQL SECURITY
特性是DEFINER
還是INVOKER
。如果安全特性為DEFINER
,則函式會以DEFINER
帳戶的權限執行。如果特性為INVOKER
,則函式會以檢視的SQL SECURITY
特性所確定的權限執行。
範例:檢視可能會依賴預存函式,而該函式可能會調用其他預存常式。例如,以下檢視調用預存函式 f()
CREATE VIEW v AS SELECT * FROM t WHERE t.id = f(t.name);
假設 f()
包含類似以下的語句
IF name IS NULL then
CALL p1();
ELSE
CALL p2();
END IF;
當 f()
執行時,需要檢查在 f()
內執行語句所需的權限。這可能意味著需要 p1()
或 p2()
的權限,具體取決於 f()
內的執行路徑。這些權限必須在執行時檢查,並且必須擁有權限的使用者由檢視 v
和函式 f()
的 SQL SECURITY
值決定。
檢視的 DEFINER
和 SQL SECURITY
子句是對標準 SQL 的擴充。在標準 SQL 中,檢視是使用 SQL SECURITY DEFINER
的規則處理的。標準規定檢視的定義者(與檢視的綱要所有者相同)會取得檢視的適用權限(例如,SELECT
),並可以授與這些權限。MySQL 沒有綱要「所有者」的概念,因此 MySQL 添加了一個子句來識別定義者。DEFINER
子句是一種擴充,其意圖是擁有標準所擁有的內容;也就是說,永久記錄誰定義了檢視。這就是為什麼預設的 DEFINER
值是檢視建立者的帳戶。
選用的 ALGORITHM
子句是 MySQL 對標準 SQL 的擴充。它會影響 MySQL 處理檢視的方式。ALGORITHM
採用三個值:MERGE
、TEMPTABLE
或 UNDEFINED
。如需更多資訊,請參閱第 27.6.2 節,「檢視處理演算法」,以及第 10.2.2.4 節,「使用合併或實體化來最佳化衍生資料表、檢視參考和通用資料表運算式」。
某些檢視是可更新的。也就是說,您可以在 UPDATE
、DELETE
或 INSERT
等語句中使用它們來更新基礎資料表的內容。為了使檢視可更新,檢視中的列與基礎資料表中的列之間必須存在一對一的關係。還有一些其他結構會使檢視不可更新。
檢視中的產生欄位被視為可更新,因為可以對其進行賦值。但是,如果明確更新此類欄位,則唯一允許的值是 DEFAULT
。有關產生欄位的資訊,請參閱第 15.1.20.8 節,「CREATE TABLE 和產生欄位」。
可以為可更新的檢視提供 WITH CHECK OPTION
子句,以防止插入或更新除了 select_statement
中的 WHERE
子句為 true 的列以外的列。
在可更新檢視的 WITH CHECK OPTION
子句中,當檢視是根據另一個檢視定義時,LOCAL
和 CASCADED
關鍵字會決定檢查測試的範圍。LOCAL
關鍵字將 CHECK OPTION
限制為僅適用於正在定義的檢視。CASCADED
會導致也會評估基礎檢視的檢查。當未提供任何關鍵字時,預設值為 CASCADED
。
有關可更新檢視和 WITH CHECK OPTION
子句的更多資訊,請參閱第 27.6.3 節,「可更新和可插入的檢視」,以及第 27.6.4 節,「檢視 WITH CHECK OPTION 子句」。