2021年6月25日 星期五

9.8 View

View 這個物件可以視作是一個虛擬的表格,本身沒有實體的存在,只能透過 Data Dictionary 得知其相關資訊, View 的內容是由一個或多個 Table 所構成,主要的目的是為了增加資料庫的安全性以及簡化程式碼,例如在 emp 這個表格當中,裡面的薪資 (salary) 欄位是一個敏感性資料,那麼就可以建立一個 View ,內容包含了 emp 除了薪資 (salary) 以外的欄位,未來只要授權使用者只能查詢 View 而不直接查詢原始 emp 這個 Table ,這樣就可以用來保護敏感性資料。使用 create view 語法建立 v_emp , v_emp 是沒有包含薪資 (salary) 這個敏感性資料:


除此之外,當我們有一段 SQL 語法,裡面有些運算式或是 join 條件式,那麼也可以把這麼一段語法建立成 View ,之後如果需要撈取這部分的資料,只要簡單的查詢 View 就好,不用再執行一大段 SQL 語法了。例如 DBA 用來查詢 Redo Log 的語法,需要 join v$log 與 v$logfile 才能得到相關訊息:


SQL> select a.group#,b.member,a.bytes/1024/1024 mb,a.status

       from v$log a, v$logfile b 

      where a.group#=b.group#;


這時就可以把上述語法建立成一個 View ,未來要查詢 Redo Log 相關資訊只需要查詢這個 View 就好,不用再執行這麼複雜的語法了:


雖然 View 簡化了 SQL 語法,但是實際上執行的還是原本複雜的語法,如果 SQL 效能上有問題的話,必須還是要回去優化原本的 SQL 語法,單就 View 本身不會有效能上的改善。


View 本身雖然是一個虛擬的存在,但實際上它的內容是可以有條件被更新的 (Insert 、 Delete 、 Update) ,只要 View 本身可以判斷此欄位是來自於原生哪一個 Table 的欄位,那麼就可以成功更新 View 的資料,在此要注意的是,雖然是對 View 做更新,但實際上是會把資料 Update 回原始的 Table ,例如將 v_emp 這個 View 做 Update ,把 employee_id=199 的 department_id 更新為 10 :


雖然是針對 v_emp 做 update ,但是我們回去查詢原始的 emp 這個 Table ,會發現 employee_id=199 的 department_id 被更新為 10 了:


v_emp 可以被更新是因為這個 View 的內容只是很簡單的來自於單一個 Table emp ,並且沒有經過任何修飾與運算,所以 View 可以很簡單的判斷要去更新哪一個 Table 的哪個欄位,如果是一個比較複雜的 View ,那麼就有可能沒有辦法直接透過 View 更新了,例如建立一個 View 的內容是關於產品的總銷售收入 (earnings) ,這個欄位是由總銷售數量與產品價格所相乘起來:


由於 earnings 欄位是一個經過運算出來的欄位,因此 View 無法判斷此欄位的正確來源,這個時候就沒有辦法對這個 View 的這個欄位做 Update 了:


如果不想讓 View 可以被更新的話,在建立時可以加上 with read only ,這樣 View 就只能唯獨不容許更新了:


除此之外, View 也可以加上 with check option ,用來限制這個 View 的內容只能在某些區間,即便更新了也不可以超出這個範圍,例如建立一個 View 限制 department_id >= 50 ,在有 with check option 的條件下,就不能把 department_id 更新為 50 以下:


View 本身也是一連串的 SQL 語法所構成,在建立的過程當中會檢查 SQL 語法是否正確,如果語法有問題, View 就無法建立,但是可以透過 force 來強制建立 View ,只不過建立起來後 View 的狀態是 compilation errors 仍然不可用,還是必須解決語法上的問題才行:


要得知 View 的相關資訊可以透過 dba_views 或是 user_views 來查詢:



沒有留言:

張貼留言