文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 參考手冊  /  ...  /  CREATE VIEW 陳述式

15.1.23 CREATE VIEW 陳述式

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 VIEWCREATE VIEW 相同。如果檢視表存在,CREATE OR REPLACE VIEW 會取代它。

關於檢視表使用限制的資訊,請參閱 第 27.10 節「檢視表的限制」

select_statement 是一個 SELECT 陳述式,提供檢視表的定義。(從檢視表選取,實際上是使用 SELECT 陳述式。)select_statement 可以從基本表格或其他檢視表選取。如同 CREATE TABLE ... SELECTSELECT 陳述式可以使用 VALUES 陳述式作為其來源,或可以用 TABLE 陳述式取代。

檢視表定義在建立時會 凍結,且不受基礎表格定義後續變更的影響。例如,如果檢視表定義為表格上的 SELECT *,稍後加入表格的新欄不會成為檢視表的一部分,而從表格中刪除的欄在從檢視表選取時會導致錯誤。

ALGORITHM 子句會影響 MySQL 處理檢視表的方式。DEFINERSQL 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 關鍵字之後的選項,例如 ALLDISTINCTSQL_SMALL_RESULT,以及諸如 INTOFOR UPDATEFOR SHARELOCK IN SHARE MODEPROCEDURE 等子句。

如果您透過變更系統變數來變更查詢處理環境,從檢視表取得的結果可能會受到影響。

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)

當執行參考檢視表的陳述式時,DEFINERSQL SECURITY 子句會決定在檢查檢視表的存取權限時要使用的 MySQL 帳戶。有效的 SQL SECURITY 特徵值為 DEFINER(預設值)和 INVOKER。這些值分別表示必要的權限必須由定義或叫用檢視表的使用者持有。

如果存在 DEFINER 子句,則 user 值應為指定為 'user_name'@'host_name'CURRENT_USERCURRENT_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_USERDEFINER 值。

MySQL 會這樣檢查檢視表權限:

  • 在檢視定義時,檢視建立者必須擁有使用檢視所存取的最上層物件所需的權限。例如,如果檢視定義引用了資料表欄位,建立者必須對定義的選取清單中的每個欄位都具有某些權限,並且對定義中其他地方使用的每個欄位都具有 SELECT 權限。如果定義引用了預存函式,則只能檢查呼叫該函式所需的權限。函式呼叫時所需的權限只能在執行時檢查:對於不同的呼叫,可能會執行函式內的不同執行路徑。

  • 引用檢視的使用者必須具有適當的權限才能存取它(SELECT 以從中選取,INSERT 以插入其中,等等)。

  • 當引用檢視時,針對檢視所存取的物件的權限會根據檢視的 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 值決定。

檢視的 DEFINERSQL SECURITY 子句是對標準 SQL 的擴充。在標準 SQL 中,檢視是使用 SQL SECURITY DEFINER 的規則處理的。標準規定檢視的定義者(與檢視的綱要所有者相同)會取得檢視的適用權限(例如,SELECT),並可以授與這些權限。MySQL 沒有綱要「所有者」的概念,因此 MySQL 添加了一個子句來識別定義者。DEFINER 子句是一種擴充,其意圖是擁有標準所擁有的內容;也就是說,永久記錄誰定義了檢視。這就是為什麼預設的 DEFINER 值是檢視建立者的帳戶。

選用的 ALGORITHM 子句是 MySQL 對標準 SQL 的擴充。它會影響 MySQL 處理檢視的方式。ALGORITHM 採用三個值:MERGETEMPTABLEUNDEFINED。如需更多資訊,請參閱第 27.6.2 節,「檢視處理演算法」,以及第 10.2.2.4 節,「使用合併或實體化來最佳化衍生資料表、檢視參考和通用資料表運算式」

某些檢視是可更新的。也就是說,您可以在 UPDATEDELETEINSERT 等語句中使用它們來更新基礎資料表的內容。為了使檢視可更新,檢視中的列與基礎資料表中的列之間必須存在一對一的關係。還有一些其他結構會使檢視不可更新。

檢視中的產生欄位被視為可更新,因為可以對其進行賦值。但是,如果明確更新此類欄位,則唯一允許的值是 DEFAULT。有關產生欄位的資訊,請參閱第 15.1.20.8 節,「CREATE TABLE 和產生欄位」

可以為可更新的檢視提供 WITH CHECK OPTION 子句,以防止插入或更新除了 select_statement 中的 WHERE 子句為 true 的列以外的列。

在可更新檢視的 WITH CHECK OPTION 子句中,當檢視是根據另一個檢視定義時,LOCALCASCADED 關鍵字會決定檢查測試的範圍。LOCAL 關鍵字將 CHECK OPTION 限制為僅適用於正在定義的檢視。CASCADED 會導致也會評估基礎檢視的檢查。當未提供任何關鍵字時,預設值為 CASCADED

有關可更新檢視和 WITH CHECK OPTION 子句的更多資訊,請參閱第 27.6.3 節,「可更新和可插入的檢視」,以及第 27.6.4 節,「檢視 WITH CHECK OPTION 子句」