CREATE VIEW
視圖(View)是一種虛擬表,由一個或多個表的查詢結果構成的,但它并不存儲實際的數據。視圖可以簡化復雜查詢,增強數據安全性。本文介紹如何使用CREATE VIEW
語法創建視圖。
注意事項
AnalyticDB for MySQL集群的視圖與MySQL視圖兼容性:
3.1.9.0之前版本
AnalyticDB for MySQL集群未兼容MySQL默認行為,當您的視圖有新增或刪除列的變更,在使用
SELECT * FROM <view_name>;
查詢時,行為上會與MySQL不一致,檢測到列數不相等,直接判定視圖不可用,出現報錯View '<view_name>' is stale; it must be re-created
。3.1.9.0及之后版本
AnalyticDB for MySQL集群兼容了MySQL默認行為。在創建視圖時,會將SQL輸出的
*
解析成具體列,再保存SQL,在增加和刪除列的行為上不再產生影響。
因此,推薦使用3.1.9.0及之后版本的集群兼容MySQL的默認行為,符合標準,避免非預期的情況發生。并盡量避免在視圖中使用*
,帶來不確定的語意和報錯。
查看企業版或湖倉版集群的內核版本,請執行SELECT adb_version();
。如需升級內核版本,請聯系技術支持。
3.1.9.0及之后版本的AnalyticDB for MySQL集群兼容MySQL行為后,可能會出現特殊副作用。例如,將列名為C的列RENAME為D列時,在需要準確引用A,B,C
三列,由于C列已不存在,會導致視圖不可用報錯,這是合理的預期。即使上層的查詢最終沒有使用C列也會報錯,因為裁剪列是優化階段,而檢查SQL語法和鑒權是解析階段。然而,3.1.9.0之前版本實現,由于只檢查視圖列數(RENAME后列數相等)和當前*
所引用列數的一致性,因此所有檢查都能通過,不會報錯。視圖可用性檢查通過后,C列被映射到基表順序中的第三列,甚至,在RENAME后再查詢C列時,依然不會報錯,此時查詢的結果是非預期的。
如果您的業務確實需要兼容AnalyticDB for MySQL3.1.9.0之前版本的特殊行為,在創建視圖時,可以加上特定Hint或配置控制達到預期。
單個視圖,增加
/*+LOG_VIEW_SELECT_ASTERISK_MYSQL_MODE=false*/
。示例如下:/*+LOG_VIEW_SELECT_ASTERISK_MYSQL_MODE=false*/ CREATE VIEW v0 AS SELECT * FROM base0;
全局配置,通過
SET ADB_CONFIG LOG_VIEW_SELECT_ASTERISK_MYSQL_MODE = false;
實現。
語法
CREATE
[OR REPLACE]
[SQL SECURITY { DEFINER | INVOKER }]
VIEW view_name
AS select_statement;
參數 | 是否必填 | 說明 |
| 選填 | 根據是否存在重名視圖,選擇對應的規則來創建視圖。具體規則如下:
說明 若未設置該參數,當新建的視圖名稱與已存在視圖重名時,會創建失敗。 |
| 定義查詢視圖的數據時的安全驗證方式,支持如下取值:
說明
| |
| 必填 | 視圖的名字。 說明 您也可以在視圖名字前加上數據庫名稱來定義該視圖所屬的數據庫,例如 |
| 視圖中的數據來源。 |
示例
數據準備
通過AnalyticDB for MySQL高權限賬號執行如下操作:
創建賬號
user1
,語句如下:CREATE USER user1 IDENTIFIED BY 'user1_pwd';
已創建數據庫
adb_demo
,并在庫中創建表t1
,建表語句如下:Create Table `t1` ( `id` bigint AUTO_INCREMENT, `id_province` bigint NOT NULL, `user_info` varchar, primary key (`id`) ) DISTRIBUTED BY HASH(`id`);
往表
t1
中插入測試數據,語句如下:INSERT INTO t1(id_province,user_info) VALUES (1,'Tom'),(1,'Jerry'),(2,'Jerry'),(3,'Mark');
創建視圖
說明本文示例以在創建視圖(視圖數據來源于表
t1
)時設置不同的安全驗證方式為例,介紹DEFINER、INVOKER的不同權限效果。創建視圖
v1
時,設置SQL SECURITY
為INVOKER
,語句如下:CREATE SQL SECURITY INVOKER VIEW v1 AS SELECT id_province,user_info FROM t1 WHERE id_province=1;
創建視圖
v2
時,設置SQL SECURITY
為DEFINER
,語句如下:CREATE SQL SECURITY DEFINER VIEW v2 AS SELECT id_province,user_info FROM t1 WHERE id_province=1;
創建視圖
v3
時,不設置SQL SECURITY
(即系統默認使用INVOKER
),語句如下:CREATE VIEW v3 AS SELECT id_province,user_info FROM t1 WHERE id_province=1;
權限對比
僅通過高權限賬號授予
user1
查詢3個視圖的權限,語句如下:GRANT SELECT ON adb_demo.v1 TO 'user1'@'%'; GRANT SELECT ON adb_demo.v2 TO 'user1'@'%'; GRANT SELECT ON adb_demo.v3 TO 'user1'@'%';
此時,使用
user1
賬號連接AnalyticDB for MySQL集群的adb_demo
數據庫后,user1
僅能查詢視圖v2
數據。查詢語句如下:SELECT * FROM v2
查詢結果如下:
+-------------+-----------+ | ID_PROVINCE | USER_INFO | +-------------+-----------+ | 1 | Tom | | 1 | Jerry | +-------------+-----------+
而通過SELECT語句查詢
v1
或v3
視圖數據時則會報錯。查詢語句如下:SELECT * FROM v1
或
SELECT * FROM v3
執行上述語句進行查詢時,均會返回如下錯誤:
ERROR 1815 (HY000): [20049, 2021083110261019216818804803453927668] : Failed analyzing stored view
在授予
user1
查詢3個視圖的權限基礎上,再通過高權限賬號授予user1
查詢t1
表的權限,語句如下:GRANT SELECT ON adb_demo.t1 to user1@'%';
此時,使用
user1
賬號連接AnalyticDB for MySQL集群的adb_demo
數據庫后,user1
賬號能夠查詢全部視圖v1
、v2
和v3
的數據,查詢語句如下:SELECT * FROM v1
或
SELECT * FROM v2
或
SELECT * FROM v3
執行上述3條查詢語句均會返回相同的結果,結果如下:
+-------------+-----------+ | ID_PROVINCE | USER_INFO | +-------------+-----------+ | 1 | Tom | | 1 | Jerry | +-------------+-----------+
最佳實踐
更多詳情,請參見通過視圖管控數據權限。