0 序言
本文將系統講解數據庫中視圖的相關知識
,包括視圖的定義
、作用
、創建
(單表、多表、基于視圖創建)、查看
、更新
、修改
與刪除
操作,以及視圖的優缺點。
通過學習,你能夠掌握視圖的基本概念,理解何時及如何合理使用視圖,提升數據庫操作的靈活性與安全性。
1 常見的數據庫對象
數據庫包含多種對象,各自承擔不同功能,具體如下:
1.1 表(TABLE)
是存儲數據的邏輯單元
,以行和列的形式存在,列即字段,行即記錄。
1.2 數據字典
是系統表,存放數據庫相關信息,數據通常由數據庫系統維護,程序員一般只可查看,不應修改。
1.3 約束(CONSTRAINT)
用于執行數據校驗的規則,目的是保證數據的完整性。
1.4 視圖(VIEW)
是一個或多個數據表里數據的邏輯顯示,本身不存儲數據。
1.5 索引(INDEX)
用于提高查詢性能,類似書的目錄。
1.6 存儲過程(PROCEDURE)
用于完成一次完整的業務處理,無返回值,但可通過傳出參數傳遞多個值給調用環境。
1.7 存儲函數(FUNCTION)
用于完成一次特定的計算,具有一個返回值。
1.8 觸發器(TRIGGER)
相當于事件監聽器,當數據庫發生特定事件后被觸發,完成相應處理。
2. 視圖概述
2.1 為什么使用視圖
數據訪問控制:可針對不同用戶提供不同查詢視圖,限制數據可見范圍,如對銷售人員隱藏采購價格、對普通員工隱藏薪酬敏感字段。
簡化查詢:將常用查詢結果集封裝為視圖,減少重復編寫復雜查詢語句的工作量。
數據格式化:可對數據進行格式化處理,方便按特定格式展示,如拼接員工姓名與部門名。
2.2 視圖的理解
視圖是一種虛擬表,本身不存儲數據,僅占用少量內存空間,其數據來源于基表
(賴以建立的已有表)。
視圖的創建和刪除僅影響自身
,不影響基表;但對視圖數據的增刪改會同步影響基表,反之亦然。
視圖的數據由SELECT語句
提供,自身不保存數據,僅作為基表數據的另一種表現形式。
3. 創建視圖
3.1 基本語法
CREATE [OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 視圖名稱 [(字段列表)]
AS 查詢語句
[WITH [CASCADED|LOCAL] CHECK OPTION]
精簡版:CREATE VIEW 視圖名稱 AS 查詢語句
3.2 創建單表視圖
3.2.1 示例1:直接使用SELECT字段作為視圖字段
-- 創建視圖empvu80,包含80號部門員工的ID、姓氏、薪資
CREATE VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM employees
WHERE department_id = 80;-- 查詢視圖
SELECT * FROM empvu80;
3.2.2 示例2:指定視圖字段別名
-- 創建視圖emp_year_salary,包含員工姓名和年薪(含傭金)
CREATE VIEW emp_year_salary (ename, year_salary)
AS
SELECT ename, salary*12*(1+IFNULL(commission_pct,0))
FROM t_employee;
這里要注意一點:
若未指定視圖字段列表,默認與SELECT語句字段列表一致;
若SELECT字段有別名,視圖字段名與別名相同
。
3.3 創建多表聯合視圖
3.3.1 示例1:兩表內連接
-- 創建視圖empview,關聯員工表和部門表,包含員工ID、姓名、部門名
CREATE VIEW empview
AS
SELECT employee_id emp_id, last_name NAME, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;
3.3.2 示例2:帶聚合函數的聯合視圖
-- 創建視圖dept_sum_vu,統計各部門薪資的最小、最大、平均值
CREATE VIEW dept_sum_vu (name, minsal, maxsal, avgsal)
AS
SELECT d.department_name, MIN(e.salary), MAX(e.salary), AVG(e.salary)
FROM employees e, departments d
WHERE e.department_id = d.department_id
GROUP BY d.department_name;
3.3.3 示例3:數據格式化視圖
-- 創建視圖emp_depart,格式化員工姓名與部門名(格式:姓名(部門名))
CREATE VIEW emp_depart
AS
SELECT CONCAT(last_name,'(',department_name,')') AS emp_dept
FROM employees e JOIN departments d
WHERE e.department_id = d.department_id;
3.4 基于視圖創建視圖
基于emp_dept和emp_year_salary視圖創建新視圖
-- 創建視圖emp_dept_ysalary,包含員工姓名、部門名、年薪
CREATE VIEW emp_dept_ysalary
AS
SELECT emp_dept.ename, dname, year_salary
FROM emp_dept INNER JOIN emp_year_salary
ON emp_dept.ename = emp_year_salary.ename;
4. 查看視圖
4.1 查看數據庫中的視圖對象
-- 顯示數據庫中所有表和視圖
SHOW TABLES;
4.2 查看視圖結構
-- 查看視圖empvu80的結構
DESC empvu80;
-- 或
DESCRIBE empvu80;
4.3 查看視圖屬性信息
-- 查看視圖empvu80的存儲引擎、版本等信息(Comment為VIEW表示是視圖)
SHOW TABLE STATUS LIKE 'empvu80'\G
4.4 查看視圖詳細定義
-- 查看視圖empvu80的創建語句
SHOW CREATE VIEW empvu80;
5. 更新視圖的數據
5.1 一般情況
MySQL支持通過INSERT、UPDATE、DELETE操作視圖數據,且會同步影響基表,反之亦然。
示例1:UPDATE操作
-- 修改emp_tel視圖中"孫洪亮"的電話
UPDATE emp_tel SET tel = '13789091234' WHERE ename = '孫洪亮';
-- 基表t_employee中對應數據同步更新
SELECT ename,tel FROM t_employee WHERE ename = '孫洪亮'; -- 結果:孫洪亮 13789091234
這里跟上文約束那一篇里面寫到的主表跟從表,
有個示例也是效果如此。
一個表的信息變動另一個表相關聯的信息也會隨著更新。
示例2:DELETE操作
-- 刪除emp_tel視圖中"孫洪亮"的記錄
DELETE FROM emp_tel WHERE ename = '孫洪亮';
-- 基表t_employee中對應記錄同步刪除
SELECT ename,tel FROM t_employee WHERE ename = '孫洪亮'; -- 結果:空集
5.2 不可更新的視圖
當視圖滿足以下情況時,不支持INSERT、UPDATE、DELETE操作:
- 定義時指定
ALGORITHM = TEMPTABLE
(不支持INSERT、DELETE); - 不包含基表中所有非空且無默認值的列(不支持INSERT);
SELECT語句使用JOIN聯合查詢
(不支持INSERT、DELETE);- 字段列表包含數學表達式或子查詢(不支持INSERT,且無法UPDATE該字段);
- 使用
DISTINCT
、聚合函數
、GROUP BY
、HAVING
、UNION
等(不支持增刪改); - SELECT包含子查詢且引用FROM后的表(不支持增刪改);
- 基于
不可更新的視圖創建
; - 常量視圖。
比如說:
-- 創建基于兩表連接的視圖emp_dept
CREATE VIEW emp_dept
AS SELECT ename,salary,birthday,tel,email,hiredate,dname
FROM t_employee INNER JOIN t_department
ON t_employee.did = t_department.did;-- 插入數據會失敗(JOIN視圖不支持INSERT)
INSERT INTO emp_dept(ename,salary,birthday,tel,email,hiredate,dname)
VALUES('張三',15000,'1995-01-08','18201587896','zs@atguigu.com','2022-02-14','新部門');
這里會報錯,錯誤內容:Can not modify more than one base table through a join view
意思就是說,你現在這個JOIN視圖不支持用INSERT語法進行插入數據。
6. 修改與刪除視圖
6.1 修改視圖
方式1:使用CREATE OR REPLACE VIEW
-- 修改empvu80視圖,包含員工ID、全名(名+姓)、薪資、部門ID
CREATE OR REPLACE VIEW empvu80
(id_number, name, sal, department_id)
AS
SELECT employee_id, first_name || ' ' || last_name, salary, department_id
FROM employees
WHERE department_id = 80;
這里的圖片還不夠直觀,
補充上姓名數據會看起來更加直觀,
就好比本來是張 三,一個放在lastname,一個在firstname,
然后這里的作用就是變成一個name里面存放的就是張三
。
方式2:使用ALTER VIEW
-- 修改視圖salvu50的查詢條件
ALTER VIEW salvu50
AS
SELECT employee_id ID_NUMBER, last_name NAME, salary*12 ANN_SALARY
FROM employees
WHERE department_id = 60; -- 原條件為department_id = 50
同理,這種方法也能實現相同的效果。
6.2 刪除視圖
-- 刪除視圖empvu80(IF EXISTS避免視圖不存在時報錯)
DROP VIEW IF EXISTS empvu80;
說明:刪除基視圖會導致依賴它的視圖查詢失敗,需手動維護。
7 小結
7.1 視圖的優點
操作簡單:封裝復雜查詢,簡化開發人員對數據庫的操作,無需關注基表結構與關聯關系。
減少數據冗余:僅存儲查詢語句,不占用數據存儲資源。
數據安全:限制用戶訪問范圍,通過視圖隔離用戶與基表,保障數據安全。
適應需求變化:減少因基表結構變更帶來的工作量。
分解復雜邏輯:將復雜查詢拆分為多個視圖,組合完成復雜邏輯。
7.2 視圖的不足
維護成本高:基表結構變更時需同步維護視圖,嵌套視圖維護更復雜。
潛在隱患:視圖定義可能包含重命名、復雜邏輯,降低可讀性,增加系統風險。
過多視圖問題:實際項目中視圖過多會增加數據庫維護難度。
通過本文學習,我們要掌握視圖的創建、操作及應用場景,合理使用視圖提升數據庫操作效率與安全性。