1. 程式人生 > 其它 >第14章_檢視

第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 BYHAVINGUNION等,檢視將不支援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 查詢可能會對欄位重新命名,也可能包含複雜的邏輯,這些都會增加維護的成本。

實際專案中,如果檢視過多,會導致資料庫維護成本的問題。

所以,在建立檢視的時候,你要結合實際專案需求,綜合考慮檢視的優點和不足,這樣才能正確使用檢視,使系統整體達到最優。