資料庫複習4——視圖,資料庫複習視圖
資料庫複習CH6 視圖6.1 視圖的概念
視圖是從一個或多個表(或視圖)匯出的虛表,DBMS僅在資料字典中存放視圖的定義,而視圖的資料仍然實際儲存於匯出它的基表中
Tutorial D中定義視圖的基本語句如下:
VAR <view_name> VIEW (<relational_condition>) {<property_list>};
那麼視圖有什麼作用呢?
- 為hidden data提供安全性,即屏蔽某些不希望外界使用者看到的機密資料
- 提供一種簡寫的方式,有了視圖的預先定義,某些時候能夠避免寫繁雜的select複合運算式
- 讓同一資料為不同使用者同時從不同角度展示資料
- 提供邏輯資料獨立性,即當概念層的模式(基本表結構變化)發生改變時,外部層的模式不需要改變,因此外部的使用者程式也不需要改變
- 視圖的定義結合了外部模式函數和外部層-概念層的映射函數
- 視圖為基表添加可擴充性
- 視圖也能完成對基表的重構
6.2 視圖的操作
C.J.Date從形式化的角度來定義視圖的兩種操作:檢索(Retrieval)和更新(Update)
定義在資料庫(表)D上執行操作X得到視圖V,即V=X(D)
,則對V視圖進行檢索就是R(V)=R(X(D))=X'(D)
,也就是說對視圖檢索相當於對它的基表檢索
需要注意的是如果V=X(D)
被實現(Materializing)了,那麼X(D)就是是基本表的一份拷貝,對V的操作和D獨立開來;如果V=X(D)
只是一個虛表,那麼對V的操作會直接修改基本表D(大多數DBMS是採取後種方案)
如果定義U為更新操作,那麼U(V)=U(X(D))
,但是我們可以發現U(X(D))
和X(U'(D))
並不能等價,原因就是V的定義操作X可能涉及集合操作UNION或者from從句的JOIN等複雜操作,此時Update操作對於基本表來說存在歧義,是無法執行的
比如說V=A UNION B
,去update一個元組到底是更新基表A中的元組還是更新基表B中的元組還是AB同時更新;又比如說去insert一個元組不滿足B的完整性條件約束但滿足A的完整性條件約束,是只插入A還是整個插入操作失敗
PPT和書上有很多例子來闡述這個問題,我們需要掌握的核心就是對視圖的更新操作存在某些限制,不是所有視圖都能夠更新
6.3 SQL視圖(1)建立視圖
SQL中定義一個視圖的文法如下:
create view <view_name> as <query expression>;
query expression可以是任何合法的select查詢運算式,如定義一個“好供應商”視圖:
create view good_supplier as select S.s#, S.status, S.city from Swhere s.status > 15;
query expression也可以有彙總函式、集合操作等等,SQL定義View還支援在View後面跟上屬性list作為屬性名稱(當然也可以用select as做重新命名實現),如為各部門的員工銷售額統計建立一個視圖:
create view dept_summary(name, minsal, maxsal, avgsal)as select dname, min(sal), max(sal), avg(sal) from EMP, DEPT where DEPT.d# = EMP.d# group by dname;
(2)視圖檢索
對視圖檢索的文法和對錶檢索是一樣的,都用select語句,如:
select name from dept_summary where avgsal > 2000;
這句話等價於對基表進行如下檢索:
select dname as name from EMP, DEPT where EMP.d# = DEPT.d#group by dame having avg(sal) > 2000;
(3)視圖更新
大多數SQL的實現(Oracle、MySQL等)支援對單一關係上的簡單視圖做更新操作,簡單視圖是如下的視圖:
- 不包括以下操作:JOIN、UNION、INTERSECT、EXCEPT
- 不包含關鍵字:DISTINCT
- SELECT從句只能包含簡單表名(即不包含彙總函式)
- 不能出現GROUP BY從句
- 子查詢不能包含在查詢以外的對同表的引用
註:這裡所說的視圖更新包含了update、insert、delete三個操作
但是我們發現即使是對單一關係上的簡單視圖做更新操作,也會出現問題,如在好供應商表中update某個供應商的status值:
update good_supplier set status = 10 where S# = 's1';
DBMS翻譯成
update S set status = 10 where status > 15 and S# = 's1';
執行,而視圖good_supplier的定義並沒更改,那麼執行了這句話供應商s1雖然在基礎資料表中的status值變成10了,但是該供應商s1卻再也不屬於good_supplier了,邏輯上出錯(更新了視圖卻直接刪掉了元組)
SQL為了防止上述情況的發生,支援在視圖定義時插入with check option
尾碼進行檢查上述類似的邏輯錯誤,如果好供應商有如下定義:
create view good_supplier as select S.s#, S.status, S.city from Swhere s.status > 15with check option;
那麼如上所述產生邏輯錯誤的update語句便不滿足檢查條件,DBMS會通知使用者執行失敗