視圖是一個**命名的 SELECT 查詢**,不存儲物理數據(虛表)。查詢視圖時,MySQL 將視圖定義合併到外層查詢中重寫執行。基表數據變更,視圖即時反映。
CREATE [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
[DEFINER = user]
[SQL SECURITY {DEFINER | INVOKER}]
VIEW view_name [(col_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
ALGORITHM=MERGE(默認):視圖定義合併到外層查詢,**可使用索引**、性能最優ALGORITHM=TEMPTABLE:先將視圖結果物化到臨時表再查詢,**不可用索引**、用於不可合併的聚合/子查詢SQL SECURITY DEFINER:以創建者權限執行(可繞過調用者權限限制)WITH CHECK OPTION:插入/更新時強制滿足視圖 WHERE 條件,防止「更新穿透」導致數據不再可見-- user, course, user_course (中間表)
-- 數據見原文
CREATE VIEW view_user_course AS
SELECT uc.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;
-- 原來需寫三表 JOIN
SELECT username, coursename FROM view_user_course WHERE username = '小張';
**並非所有視圖都可增刪改**,規則如下:
| 視圖類型 | 可更新操作 | 條件 |
|---|---|---|
| 單基表、一對一映射、無聚合/子查詢/UNION | INSERT/UPDATE/DELETE 全支持 | 視圖含基表所有非空無默認值列 |
| 多表 JOIN(一對多) | 僅可 UPDATE 單表列 | 單條 UPDATE 只修改一方基表,且無衝突 |
| 多表 JOIN | ❌ INSERT/DELETE/多表 UPDATE | 無法確定目標行/歸屬 |
| 含聚合/去重/子查詢/常量列 | ❌ 所有寫操作 | 非一對一映射 |
-- 可更新:單表視圖
CREATE VIEW view_user_keyinfo AS SELECT id, account, name FROM user;
INSERT INTO view_user_keyinfo (account, name) VALUES ('t','t'); -- ✅
UPDATE view_user_keyinfo SET name='new' WHERE id=1; -- ✅
-- 受限:多表 JOIN 視圖
UPDATE view_user_course SET coursename='JAVA' WHERE id=1; -- ✅ (只改 course 表)
UPDATE view_user_course SET username='x' WHERE id=3; -- ✅ (只改 user 表)
UPDATE view_user_course SET username='x', coursename='y' WHERE id=3; -- ❌ 同時改兩表
DELETE FROM view_user_course WHERE id=3; -- ❌
INSERT INTO view_user_course (username, coursename) VALUES('a','b'); -- ❌
-- 僅授予視圖 SELECT 權限,隱藏 salary、address 等敏感列
GRANT SELECT ON view_user_keyinfo TO 'report_user'@'%';
-- report_user 無法訪問 user 表,也看不到被排除的列
ALGORITHM=MERGE,確保視圖定義可合併(無聚合、DISTINCT、LIMIT 等)EXPLAIN SELECT * FROM view_name 檢查是否使用索引、是否產生臨時表視圖是「SQL 的函數」:**封裝複雜性、隔離權限、解耦結構**。掌握可更新性邊界,用 MERGE 算法,配合索引,視圖既安全又高效。