第14章_檢視
1. 常見的資料庫物件
物件 | 描述 |
---|---|
表(TABLE) | 表是儲存資料的邏輯單元,以行和列的形式存在,列就是欄位,行就是記錄 |
資料字典 | 就是系統表,存放資料庫相關資訊的表。系統表的資料通常由資料庫系統維護,程式設計師通常不應該修改,只可檢視 |
約束(CONSTRAINT) | 執行資料校驗的規則,用於保證資料完整性的規則 |
檢視(VIEW) | 一個或者多個數據表裡的資料的邏輯顯示,檢視並不儲存資料 |
索引(INDEX) | 用於提高查詢效能,相當於書的目錄 |
儲存過程(PROCEDURE) | 用於完成一次完整的業務處理,沒有返回值,但可通過傳出引數將多個值傳給呼叫環境 |
儲存函式(FUNCTION) | 用於完成一次特定的計算,具有一個返回值 |
觸發器(TRIGGER) | 相當於一個事件監聽器,當資料庫發生特定事件後,觸發器被觸發,完成相應的處理 |
2. 檢視概述
2.1 為什麼使用檢視?
檢視一方面可以幫我們使用表的一部分而不是所有的表,另一方面也可以針對不同的使用者制定不同的查詢檢視。比如,針對一個公司的銷售人員,我們只想給他看部分資料,而某些特殊的資料,比如採購的價格,則不會提供給他。再比如,人員薪酬是個敏感的欄位,那麼只給某個級別以上的人員開放,其他人的查詢檢視中則不提供這個欄位。
剛才講的只是檢視的一個使用場景,實際上檢視還有很多作用。最後,我們總結檢視的優點。
2.2 檢視的理解
-
檢視是一種
虛擬表
,本身是不具有資料
的,佔用很少的記憶體空間,它是 SQL 中的一個重要概念。 -
檢視建立在已有表的基礎上, 檢視賴以建立的這些表稱為基表。
-
檢視的建立和刪除隻影響檢視本身,不影響對應的基表。但是當對檢視中的資料進行增加、刪除和修改操作時,資料表中的資料會相應地發生變化,反之亦然。
-
向檢視提供資料內容的語句為 SELECT 語句, 可以將檢視理解為儲存起來的 SELECT 語句
- 在資料庫中,檢視不會儲存資料,資料真正儲存在資料表中。當對檢視中的資料進行增加、刪除和修改操作時,資料表中的資料會相應地發生變化;反之亦然。
-
檢視,是向用戶提供基表資料的另一種表現形式。通常情況下,小型專案的資料庫可以不使用檢視,但是在大型專案中,以及資料表比較複雜的情況下,檢視的價值就凸顯出來了,它可以幫助我們把經常查詢的結果集放到虛擬表中,提升使用效率。理解和使用起來都非常方便。
3. 建立檢視
- 在 CREATE VIEW 語句中嵌入子查詢
CREATE [OR REPLACE]
[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW 檢視名稱 [(欄位列表)]
AS 查詢語句
[WITH [CASCADED|LOCAL] CHECK OPTION]
- 精簡版
CREATE VIEW 檢視名稱
AS 查詢語句
3.1 建立單表檢視
舉例:
CREATE VIEW empvu80
AS
SELECT employee_id, last_name, salary
FROM employees
WHERE department_id = 80;
查詢檢視:
SELECT *
FROM salvu80;
舉例:
CREATE VIEW emp_year_salary (ename,year_salary)
AS
SELECT ename,salary*12*(1+IFNULL(commission_pct,0))
FROM t_employee;
舉例:
CREATE VIEW salvu50
AS
SELECT employee_id ID_NUMBER, last_name NAME,salary*12 ANN_SALARY
FROM employees
WHERE department_id = 50;
說明1:實際上就是我們在 SQL 查詢語句的基礎上封裝了檢視 VIEW,這樣就會基於 SQL 語句的結果集形成一張虛擬表。
說明2:在建立檢視時,沒有在檢視名後面指定欄位列表,則檢視中欄位列表預設和SELECT語句中的欄位列表一致。如果SELECT語句中給欄位取了別名,那麼檢視中的欄位名和別名相同。
3.2 建立多表聯合檢視
舉例:
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;
CREATE VIEW emp_dept
AS
SELECT ename,dname
FROM t_employee LEFT JOIN t_department
ON t_employee.did = t_department.did;
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;
- 利用檢視對資料進行格式化
我們經常需要輸出某個格式的內容,比如我們想輸出員工姓名和對應的部門名,對應格式為 emp_name(department_name),就可以使用檢視來完成資料格式化的操作:
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.3 基於檢視建立檢視
當我們建立好一張檢視之後,還可以在它的基礎上繼續建立檢視。
舉例:聯合“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. 檢視檢視
語法1:檢視資料庫的表物件、檢視物件
SHOW TABLES;
語法2:檢視檢視的結構
DESC / DESCRIBE 檢視名稱;
語法3:檢視檢視的屬性資訊
# 檢視檢視資訊(顯示資料表的儲存引擎、版本、資料行數和資料大小等)
SHOW TABLE STATUS LIKE '檢視名稱'\G
執行結果顯示,註釋Comment為VIEW,說明該表為檢視,其他的資訊為NULL,說明這是一個虛表。
語法4:檢視檢視的詳細定義資訊
SHOW CREATE VIEW 檢視名稱;
5. 更新檢視的資料
5.1 一般情況
MySQL支援使用INSERT、UPDATE和DELETE語句對檢視中的資料進行插入、更新和刪除操作。當檢視中的資料發生變化時,資料表中的資料也會發生變化,反之亦然。
舉例:UPDATE操作
mysql> SELECT ename,tel FROM emp_tel WHERE ename = '孫洪亮';
+---------+-------------+
| ename | tel |
+---------+-------------+
| 孫洪亮 | 13789098765 |
+---------+-------------+
1 row in set (0.01 sec)
mysql> UPDATE emp_tel SET tel = '13789091234' WHERE ename = '孫洪亮';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT ename,tel FROM emp_tel WHERE ename = '孫洪亮';
+---------+-------------+
| ename | tel |
+---------+-------------+
| 孫洪亮 | 13789091234 |
+---------+-------------+
1 row in set (0.00 sec)
mysql> SELECT ename,tel FROM t_employee WHERE ename = '孫洪亮';
+---------+-------------+
| ename | tel |
+---------+-------------+
| 孫洪亮 | 13789091234 |
+---------+-------------+
1 row in set (0.00 sec)
舉例:DELETE操作
mysql> SELECT ename,tel FROM emp_tel WHERE ename = '孫洪亮';
+---------+-------------+
| ename | tel |
+---------+-------------+
| 孫洪亮 | 13789091234 |
+---------+-------------+
1 row in set (0.00 sec)
mysql> DELETE FROM emp_tel WHERE ename = '孫洪亮';
Query OK, 1 row affected (0.01 sec)
mysql> SELECT ename,tel FROM emp_tel WHERE ename = '孫洪亮';
Empty set (0.00 sec)
mysql> SELECT ename,tel FROM t_employee WHERE ename = '孫洪亮';
Empty set (0.00 sec)
5.2 不可更新的檢視
要使檢視可更新,檢視中的行和底層基本表中的行之間必須存在一對一
的關係。另外當檢視定義出現如下情況時,檢視不支援更新操作:
- 在定義檢視的時候指定了“ALGORITHM = TEMPTABLE”,檢視將不支援INSERT和DELETE操作;
- 檢視中不包含基表中所有被定義為非空又未指定預設值的列,檢視將不支援INSERT操作;
- 在定義檢視的SELECT語句中使用了
JOIN聯合查詢
,檢視將不支援INSERT和DELETE操作; - 在定義檢視的SELECT語句後的欄位列表中使用了
數學表示式
或子查詢
,檢視將不支援INSERT,也不支援UPDATE使用了數學表示式、子查詢的欄位值; - 在定義檢視的SELECT語句後的欄位列表中使用
DISTINCT
、聚合函式
、GROUP BY
、HAVING
、UNION
等,檢視將不支援INSERT、UPDATE、DELETE; - 在定義檢視的SELECT語句中包含了子查詢,而子查詢中引用了FROM後面的表,檢視將不支援INSERT、UPDATE、DELETE;
- 檢視定義基於一個
不可更新檢視
; - 常量檢視。
舉例:
mysql> CREATE OR REPLACE VIEW emp_dept
-> (ename,salary,birthday,tel,email,hiredate,dname)
-> AS SELECT ename,salary,birthday,tel,email,hiredate,dname
-> FROM t_employee INNER JOIN t_department
-> ON t_employee.did = t_department.did ;
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO emp_dept(ename,salary,birthday,tel,email,hiredate,dname)
-> VALUES('張三',15000,'1995-01-08','18201587896',
-> '[email protected]','2022-02-14','新部門');
#ERROR 1393 (HY000): Can not modify more than one base table through a join view 'atguigu_chapter9.emp_dept'
從上面的SQL執行結果可以看出,在定義檢視的SELECT語句中使用了JOIN聯合查詢,檢視將不支援更新操作。
雖然可以更新檢視資料,但總的來說,檢視作為
虛擬表
,主要用於方便查詢
,不建議更新檢視的資料。對檢視資料的更改,都是通過對實際資料表裡資料的操作來完成的。
6. 修改、刪除檢視
6.1 修改檢視
方式1:使用CREATE OR REPLACE VIEW 子句修改檢視
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;
說明:CREATE VIEW 子句中各列的別名應和子查詢中各列相對應。
方式2:ALTER VIEW
修改檢視的語法是:
ALTER VIEW 檢視名稱
AS
查詢語句
6.2 刪除檢視
-
刪除檢視只是刪除檢視的定義,並不會刪除基表的資料。
-
刪除檢視的語法是:
DROP VIEW IF EXISTS 檢視名稱;
DROP VIEW IF EXISTS 檢視名稱1,檢視名稱2,檢視名稱3,...;
-
舉例:
DROP VIEW empvu80;
-
說明:基於檢視a、b建立了新的檢視c,如果將檢視a或者檢視b刪除,會導致檢視c的查詢失敗。這樣的檢視c需要手動刪除或修改,否則影響使用。
7. 總結
7.1 檢視優點
1. 操作簡單
將經常使用的查詢操作定義為檢視,可以使開發人員不需要關心檢視對應的資料表的結構、表與表之間的關聯關係,也不需要關心資料表之間的業務邏輯和查詢條件,而只需要簡單地操作檢視即可,極大簡化了開發人員對資料庫的操作。
2. 減少資料冗餘
檢視跟實際資料表不一樣,它儲存的是查詢語句。所以,在使用的時候,我們要通過定義檢視的查詢語句來獲取結果集。而檢視本身不儲存資料,不佔用資料儲存的資源,減少了資料冗餘。
3. 資料安全
MySQL將使用者對資料的訪問限制
在某些資料的結果集上,而這些資料的結果集可以使用檢視來實現。使用者不必直接查詢或操作資料表。這也可以理解為檢視具有隔離性
。檢視相當於在使用者和實際的資料表之間加了一層虛擬表。
同時,MySQL可以根據許可權將使用者對資料的訪問限制在某些檢視上,使用者不需要查詢資料表,可以直接通過檢視獲取資料表中的資訊。這在一定程度上保障了資料表中資料的安全性。
4. 適應靈活多變的需求
當業務系統的需求發生變化後,如果需要改動資料表的結構,則工作量相對較大,可以使用檢視來減少改動的工作量。這種方式在實際工作中使用得比較多。
5. 能夠分解複雜的查詢邏輯
資料庫中如果存在複雜的查詢邏輯,則可以將問題進行分解,建立多個檢視獲取資料,再將建立的多個檢視結合起來,完成複雜的查詢邏輯。
7.2 檢視不足
如果我們在實際資料表的基礎上建立了檢視,那麼,如果實際資料表的結構變更了,我們就需要及時對相關的檢視進行相應的維護。特別是巢狀的檢視(就是在檢視的基礎上建立檢視),維護會變得比較複雜,可讀性不好
,容易變成系統的潛在隱患。因為建立檢視的 SQL 查詢可能會對欄位重新命名,也可能包含複雜的邏輯,這些都會增加維護的成本。
實際專案中,如果檢視過多,會導致資料庫維護成本的問題。
所以,在建立檢視的時候,你要結合實際專案需求,綜合考慮檢視的優點和不足,這樣才能正確使用檢視,使系統整體達到最優。