mysql 視圖
在MySQL中,創建視圖的完整語法如下:
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]
其對應的語法變量信息如下:
- [OR REPLACE]
- 中括號中的
OR REPLACE
關鍵字是可選的。如果當前數據庫中已經存在指定名稱的視圖時,沒有該關鍵字,將會提示錯誤信息;如果使用了OR REPLACE
關鍵字,則當前正在創建的視圖會覆蓋掉原來同名的視圖。 - [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
ALGORITHM
子句是可選的,它表示使用何種算法來處理視圖。此外,它並不屬於標準SQL的一部分,而是MySQL對標準SQL進行的功能擴展。ALGORITHM
可以設置三個值:MERGE
、TEMPTABLE
或UNDEFINED
。如果沒有ALGORITHM
子句,則默認值為UNDEFINED
(未定義的)。 對於MERGE
,會將引用視圖的語句的文本與視圖定義合並起來,使得視圖定義的某一部分取代語句的對應部分。對於
TEMPTABLE
,視圖的結果將被置於臨時表中,然後使用它執行語句。對於
UNDEFINED
,MySQL將選擇所要使用的算法。如果可能,它傾向於MERGE
TEMPTABLE
,這是因為MERGE
通常更有效,而且如果使用了臨時表,視圖是不可更新的。之所以提供
TEMPTABLE
選項,是因為TEMPTABLE
在創建臨時表之後、並在完成語句處理之前,能夠釋放基表上的鎖定。與MERGE
算法相比,鎖定釋放的速度更快,這樣,使用視圖的其他客戶端不會被屏蔽過長時間。此外,
MERGE
算法要求視圖中的行和基表中的行具有一對一的關系。如果視圖包含聚合函數(SUM()
,MIN()
,MAX()
,COUNT()
等)、DISTINCT
、GROUP BY
、HAVING
、UNION
或UNION ALL
、沒有基表的引用文字值(例如:SELECT ‘hello‘;
)等結構中的任何一種,將失去一對一的關系,此時必須使用臨時表取而代之。- [(column_list)]
(column_list)
用於自定義視圖中各個字段的名稱。如果沒有該命令選項,那麽通過視圖查詢到的各個字段的名稱和視圖所使用到的數據表的字段名稱保持一致。下面是一個常見的用於創建視圖的SQL語句:CREATE OR REPLACE VIEW v_user AS SELECT id, username FROM user;
由於
user
表中的字段名稱為id
和username
,因此視圖v_user
中的兩個字段名稱也分別默認為id
和username
。現在,我們將視圖v_user
中的字段名稱分別自定義為uid
和uname
。CREATE OR REPLACE VIEW v_user (uid, uname) AS SELECT id, username FROM user;
- select_statement
select_statement
用於指定視圖的內容定義。簡而言之,這裏就是用戶自定義的一個SELECT語句。- [WITH [CASCADED | LOCAL] CHECK OPTION]
- 該選項中的
CASCADED
為默認值,LOCAL CHECK OPTION
用於在可更新視圖中防止插入或更新行。由於此選項一般不使用,因此不再贅述,具體信息請參考MySQL官方網站上的相關信息。 - 如果在創建視圖的時候制定了“WITH CHECK OPTION”,那麽更新數據時不能插入或更新不符合視圖限制條件的記錄 一般默認加上
刪除視圖
在MySQL中刪除視圖的方法非常簡單,其詳細語法如下:
--刪除指定名稱的一個或多個視圖
DROP VIEW [IF EXISTS]
view_name [, view_name2]...
其中,關鍵字IF EXISTS
用於防止因視圖不存在而提示出錯,此時,只有存在該視圖才會執行刪除操作。DROP VIEW
語句可以一次性刪除多個視圖,只需要在多個視圖名稱之間以英文逗號隔開即可。如果多個視圖存在於不同的數據庫中,不數據當前數據庫的視圖名稱之前還必須加上db_name.
前綴。
--刪除視圖v_user
DROP VIEW v_user;
修改視圖
請參考創建視圖語法中的OR REPLACE
關鍵字,只要具備該關鍵字的視圖創建語句就是修改視圖的SQL語句。
查看視圖
在MySQL中,show tables
不僅可以用於查看當前數據庫中存在哪些數據表,同時也可以查看到當前數據庫中存在哪些視圖。
--執行show tables
mysql> show tables;
--以下是輸出結果
+----------------+
| Tables_in_test |
+----------------+
| user |
| v_user |
+----------------+
2 rows in set (0.00 sec)
查看視圖詳情
查看視圖詳情的方法有兩種,一種是和查看表詳情一樣使用desc 視圖名
,另外一種方法是show fields from 視圖名
:
>DESC 視圖名;
或者
>SHOW FIELDS FROM 視圖名;
不過,僅僅使用show tables
語句,在輸出結果中,我們根本無法區分到底哪些才是視圖哪些才是真實的數據表(當然,視圖的命名我們可以統一約定以"v_"開頭)。此時,我們需要使用命令show full tables
,該命令可以列出額外的table_type
列,如果對應輸出行上該列的值為"VIEW",則表示這是一個視圖。
--執行show full tables
mysql> show full tables;
--以下是輸出結果
+----------------+------------+
| Tables_in_test | Table_type |
+----------------+------------+
| user | BASE TABLE |
| v_user | VIEW |
+----------------+------------+
2 rows in set (0.00 sec)
當我們通過上述命令找到了我們所需要的視圖之後,我們可以使用如下命令查看創建該視圖的詳細語句:
show create view view_name
例如,我們使用該命令查看創建視圖v_user
的SQL語句:
--由於該語句的輸出結果較為雜亂,因此使用\G命令進行格式化輸出
mysql> show create view v_user \G;
--以下是格式化的輸出結果
*************************** 1. row ***************************
View: v_user
Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v_user` AS select `user`.`id` AS `uid`,`user`.`username`
AS `uname` from `user`
character_set_client: utf8
collation_connection: utf8_general_ci
1 row in set (0.00 sec)
-- ----------------------------
-- View structure for `view_user_course`
-- ----------------------------
DROP VIEW
IF EXISTS `view_user_course`;
CREATE ALGORITHM = UNDEFINED
DEFINER = `root`@`localhost`
SQL SECURITY DEFINER
VIEW `view_user_course` AS (
SELECT
`uc`.`id` AS `id`,
`u`.`name` AS `username`,
`c`.`name` AS `coursename`
FROM
(
(
`user` `u`
LEFT JOIN `user_course` `uc` ON ((`u`.`id` = `uc`.`userid`))
)
LEFT JOIN `course` `c` ON ((`uc`.`courseid` = `c`.`id`))
)
);
幾點說明(MySQL中的視圖在標準SQL的基礎之上做了擴展):
ALGORITHM=UNDEFINED:指定視圖的處理算法;
DEFINER=`root`@`localhost`:指定視圖創建者;
SQL SECURITY DEFINER:指定視圖查詢數據時的安全驗證方式;
procedure與function、trigger等創建時緊接著CREATE都有個definer可選項,該definer規定了訪問該procedure等的安全控制。
一、DEFINER
如:創建procedure
說明:
上面示例指定definer為用戶‘admin‘@‘localhost‘,所以任意用戶A訪問該PROCEDURE 時,能否成功取決於A是否有調用該PROCEDURE的權限,以及definer是否有procedure中的SELECT的權限。
二、SQL SECURITY
DEFINER默認為當前用戶,也可指定其他用戶。如果想通過訪問者來判斷是否具有訪問該PROCEDURE 的權限,則可用SQL SECURITY指定。
說明:
該示例雖然指定了DEFINER ,但同時也指定了SQL SECURITY 類型為INVOKER ,SQL SECURITY 優先級高,所以安全類型為INVOKER,用戶能否訪問取決於用戶是否有執行該PROCEDURE 的權限及該PROCEDURE 中的SELECT 權限(與select操作的表有關)。
當然,也可用SQL SECURITY 指定DEFINER:SQL SECURITY DEFINER
mysql 視圖