**目錄**
[TOC]
# 1 View的應用
在使用MySQL數據庫的時候,你會使用各種不同的SQL敘述來執行查詢與維護的工作。數據庫在運作一段時間后,你會發覺不論是查詢與維護的敘述,都可能會出現一些類似、而且很常使用的SQL敘述:
[](http://box.kancloud.cn/2015-09-15_55f7ef13444e1.png)
以上列的查詢敘述來說,雖然它并不是很復雜,只是一個加入排序設定的一般查詢而已。可是如果常常會執行這樣的查詢,你每次都要輸入這個查詢敘述再執行它;就算你把這個查詢敘述儲存為文字檔保存起來,需要的時候再開啟檔案使用,這樣做的話是比較方便一些,不過還是很麻煩,而且比較沒有靈活性。
如果在數據庫的應用中,出現這種很常執行的查詢敘述時,你可以在MySQL數據庫中建立一種“View”元件,View元件用來保存一段你指定的查詢敘述:
[](http://box.kancloud.cn/2015-09-15_55f7ef142092a.png)
建立好需要的View元件以后,除了有一些限制外,它使用起來就像是一個表格,所以當你需要執行這樣的查詢時,可以在查詢敘述的“FROM”子句指定一個View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef14c7b61.png)
也有很多人稱“View”元件是一種“虛擬表格”,因為它不是一個真正儲存紀錄資料的表格,可是它又跟表格的用法類似。所以如果有需要的話,你也可以使用View元件回傳的紀錄資料,執行統計、分組與其它需要的處理:
[](http://box.kancloud.cn/2015-09-15_55f7ef154580f.png)
View元件就像是一個表格,大部份使用表格可以完成的工作,也可以套用在View元件。所以把View元件和表格一起放在“FROM”子句中,執行需要的結合查詢也是可以的:
[](http://box.kancloud.cn/2015-09-15_55f7ef1fc0f67.png)
# 2 建立需要的View
不論是為了查詢或維護,如果你很常需要使用到同一個查詢敘述,你就可以考慮建立一個View元件把這個查詢敘述儲存起來。下列是建立View元件基本的語法:
[](http://box.kancloud.cn/2015-09-15_55f7ef20450b6.png)
如果你很常執行查詢“每個地區GNP最高的國家”資料,這樣的需求可以使用子查詢來完成,為了不想要每次重復輸入這個查詢敘述,你可以建立一個名稱“CountryMaxGNP”的View元件,這樣以后要執行這個查詢的時候就方便多了:
[](http://box.kancloud.cn/2015-09-15_55f7ef20b3bd5.png)
在上列建立View元件的范例中,只有“Name”與“GNP”兩個字段,如果想要在已經建立好的“CountryMaxGNP”的View元件中,再加入新的“Code”字段的話:
[](http://box.kancloud.cn/2015-09-15_55f7ef213f73e.png)
如果需要修改一個已經建立好的View元件,你就要加入“OR REPLACE”的設定,這樣才不會出現錯誤訊息:
[](http://box.kancloud.cn/2015-09-15_55f7ef219dade.png)
如果想要查詢一個View元件中會傳回哪些字段的資料,可以使用“DESCRIBE”或是比較簡短的“DESC”指令:
[](http://box.kancloud.cn/2015-09-15_55f7ef226020d.png)
下列是MySQL關于View元件的規定與限制:
* 在同一個數據庫中,View的名稱不可以重復,也不可以跟表格名稱一樣
* View不可以跟Triggers建立聯結
儲存在View中的查詢敘述也有下列的規定:
* 查詢敘述中只能使用到已存在的表格或View
* “FROM”子句中不可以使用子查詢
* 不可以使用“TEMPORARY”表格
* 不可以使用自行定義的變量、Procedure與Prepared statement參數
注:“TEMPORARY”表格在“表格與索引、建立表格、建立暫存表格”中討論。“Triggers”、定義變量、“Procedure”與“Prepared statement”在后面都會有章節詳細的討論。
結合查詢在關聯式數據庫中幾乎是必要的一種查詢,以下列查詢“國家與城市人口比例”的需求來說,就需要從“country”與“city”表格中查詢必要的字段資料:
[](http://box.kancloud.cn/2015-09-15_55f7ef23170df.png)
如果會經常執行這個結合查詢的話,你應該會很希望把它儲存為View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef236f346.png)
你不會在一個表格中,為不同的兩個字段取一樣的名稱;在使用查詢敘述提供View元件的字段時,也要注意名稱重復的問題,雖然在單純的結合查詢回傳的資料中,有一樣的字段名稱并不會造成錯誤。要解決這個錯誤有兩種方式,第一種是在查詢敘述的“SELECT”子句中,自己為名稱重復的字段取不同的字段別名:
[](http://box.kancloud.cn/2015-09-15_55f7ef24d83b2.png)
另外一種方式可以在建立View元件的時候,另外指定View元件的字段名稱:
[](http://box.kancloud.cn/2015-09-15_55f7ef256fd40.png)
這樣的作法不用修改查詢敘述,依照查詢敘述回傳的字段順序,另外指定View元件使用的字段名稱:
[](http://box.kancloud.cn/2015-09-15_55f7ef26c8fc7.png)
# 3 修改View
使用“ALTER VIEW”敘述,可以讓你修改一個已經建立好的View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef275bc06.png)
下列的范例使用“ALTER VIEW”敘述修改已經存在的“CountryMaxGNP”View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef279543d.png)
上列范例執行的工作也可以使用“CREATE OR REPLACE VIEW”敘述來完成:
[](http://box.kancloud.cn/2015-09-15_55f7ef323fd0c.png)
如果以修改View元件的工作來說,使用“ALTER VIEW”或“CREATE OR REPLACE VIEW”敘述的效果是完全一樣的。唯一的差異是要修改View元件如果不存在的話,“CREATE OR REPLACE VIEW”敘述會直接建立新的View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef3369f6e.png)
# 4 刪除View
下列的語法可以刪除一個不需要的View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef33f157e.png)
如果“DROP VIEW”敘述指定的View元件不存在的話,執行敘述以后會產生錯誤訊息:
[](http://box.kancloud.cn/2015-09-15_55f7ef3455dfa.png)
你可以在“DROP VIEW”敘述加入“IF EXISTS”,這樣就可以防止產生View元件不存在的錯誤訊息:
[](http://box.kancloud.cn/2015-09-15_55f7ef349eae7.png)
# 5 資料維護與View
View元件除了提供比較方便的查詢方式外,你也可以使用View元件來執行資料維護的工作。與View元件應用在查詢資料時提供的方便性一樣,不使用表格元件,而使用View元件來執行新增、修改或刪除的工作,也可以增加資料維護的方便性。
要使用View元件來執行新增、修改或刪除的工作,View元件所包含的查詢敘述必須符合下列的規則:
* 不可以包含計算或函式的字段
* 只允許一對一的結合查詢
* View元件的“ALGORITHM”不可以設定為“TEMPTABLE”
如果符合上列規定的View元件,就會稱為“可修改的View元件、updattable views”。只有可修改的View元件,可以使用在“INSERT”、“UPDATE”或“UPDATE”敘述中執行資料維護的工作。
注:View元件的“ALGORITHM”設定在這一章后面的“View的算法”中討論。
## 5.1 使用View元件執行資料維護
下列是一個可以執行資料維戶的View元件,它的字段沒有包含計算或函式,也沒有使用結合查詢:
[](http://box.kancloud.cn/2015-09-15_55f7ef3511e1f.png)
如果要修改員工編號“7844”的傭金為600的話,你除了可以在“UPDATE”敘述中指定修改的表格名稱為“emp”外,也可以在“UPDATE”敘述中指定View元件“EmpDept30View”:
[](http://box.kancloud.cn/2015-09-15_55f7ef3b22e3e.png)
在執行上列的“UPDATE”敘述以后,不論是查詢View元件或表格,都可以確定資料已經修改了:
[](http://box.kancloud.cn/2015-09-15_55f7ef3c12633.png)
使用“INSERT”敘述新增紀錄時,也可以指定View元件“EmpDept30View”:
[](http://box.kancloud.cn/2015-09-15_55f7ef3d1d0dc.png)
在執行上列的“INSERT”敘述以后,查詢View元件所得到的結果并沒有剛才新增的員工資料,查詢表格時才可以確定資料已經新增,這是因為新增紀錄的部門編號字段資料為“NULL”的關系:
[](http://box.kancloud.cn/2015-09-15_55f7ef3d7fe29.png)
與“INSERT”和“UPDATE”敘述一樣,“DELETE”敘述也可以指定View元件的紀錄資料:
[](http://box.kancloud.cn/2015-09-15_55f7ef3ddd807.png)
不過執行上列的刪除敘述后,千萬不要以為你已經刪除員工編號“9001”的員工紀錄了:
[](http://box.kancloud.cn/2015-09-15_55f7ef3e3772f.png)
## 5.2 使用“WITH CHECK OPTION”
你可以使用View元件來執行資料維護的工作,可是在執行新增或修改的時候,又可能會造成一些有問題的資料。如果你不希望產生這類的問題,你可以為View元件加入“WITH CHECK OPTION”的設定:
[](http://box.kancloud.cn/2015-09-15_55f7ef488897b.png)
加入“WITH CHECK OPTION”設定的View元件,在執行資料維護工作時,會先執行檢查的工作,規則是一定要符合“View元件中WHERE設定的條件”:
[](http://box.kancloud.cn/2015-09-15_55f7ef4916b08.png)
因為上列范例所新增的紀錄資料,“deptno”字段會儲存“NULL”值,這樣就違反View元件中“WHERE deptno = 30”的條件設定了,所以在執行以后會產生錯誤訊息。下列的修改敘述就可以正確的執行:
[](http://box.kancloud.cn/2015-09-15_55f7ef4e666dd.png)
View元件中的“WITH CHECK OPTION”設定,還有額外的“CASCADE”和“LOCAL”兩個控制檢查范圍的設定:
[](http://box.kancloud.cn/2015-09-15_55f7ef4ea1f07.png)
會有“CASCADE”和“LOCAL”這兩個設定的原因,是因為View元件的資料來源可以一個表格,也可以是一個View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef4f1df77.png)
查詢“EmpDept20View”后,傳回的紀錄資料包含“deptno = 20”條件,與設定在“EmpSalaryView”的“salary >= 1500”條件:
[](http://box.kancloud.cn/2015-09-15_55f7ef4fb798e.png)
檢查范圍設定為“LOCAL”的View元件,在執行資料維護的時候,只會檢查是否符合自己的條件設定:
[](http://box.kancloud.cn/2015-09-15_55f7ef501e60c.png)
如果執行資料維護的敘述違反“EmpSalaryView”的條件設定,還是可以正確的執行:
[](http://box.kancloud.cn/2015-09-15_55f7ef506742c.png)
如果你希望所有的View元件在執行資料維護的時候,都不可以出現這類的問題,就應該把View元件的檢查范圍設定為“CASCADE”:
[](http://box.kancloud.cn/2015-09-15_55f7ef55c1bbb.png)
檢查范圍設定為“CASCADE”的View元件,在執行資料維護的時候,就不能違反所有VIew元件的條件設定:
[](http://box.kancloud.cn/2015-09-15_55f7ef56699f7.png)
# 6 View的算法
View元件可以提供更方便的資料查詢與維護方式,在你建立View元件的時候,除了指定的查詢敘述要符合規定,還可以指定數據庫執行View元件時所使用的“算法、algorithm”:
[](http://box.kancloud.cn/2015-09-15_55f7ef56e6d76.png)
一般來說,你不需要特別指定View元件使用的算法。如果在建立View元件的時候,沒有指定使用的算法為“MERGE”或“TEMPTABLE”,MySQL會設定為“UNDEFINED”,這個設定表示MySQL會依照View元件中包含的敘述,自動選擇一個適合的算法,可能是“MERGE”或“TEMPTABLE”。
下列是一個算法設定為“MERGE”的View元件,在MySQL數據庫中的運作情形:
[](http://box.kancloud.cn/2015-09-15_55f7ef57c2874.png)
下列是一個算法設定為“TEMPTABLE”的View元件,在MySQL數據庫中的運作情形:
[](http://box.kancloud.cn/2015-09-15_55f7ef586f8cb.png)
并不是所有的View元件都可以指定算法設定為“MERGE”,以下列查詢員工統計資訊的敘述來說:
[](http://box.kancloud.cn/2015-09-15_55f7ef5941dae.png)
如果執行下列建立View元件的敘述,就會產生警告的訊息:
[](http://box.kancloud.cn/2015-09-15_55f7ef59a520c.png)
如果View元件包含的查詢敘述有下列的情況,MySQL都會自動把算法設定為“UNDEFINED”:
* 群組函式:SUM()、MIN()、MAX()、COUNT()
* DISTINCT
* GROUP BY
* HAVING
* UNION或UNION ALL
* “SELECT”子句中包含一個明確的值,而不是表格的字段
# 7 View的維護與資訊
## 7.1 檢驗View的正確性
在你建立一個View元件的時候,MySQL會檢查View元件包含的查詢敘述是否正確,如果沒有問題的話,才會儲存View元件的設定。不過以下列的范例來說:
[](http://box.kancloud.cn/2015-09-15_55f7ef5eea03e.png)
如果不小心刪除“EmpSalaryView”這個View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef5fb6973.png)
執行查詢“EmpDept20View”的時候,就會產生警告訊息了:
[](http://box.kancloud.cn/2015-09-15_55f7ef61161fb.png)
這樣的問題也可以經由使用檢查表格或View元件的敘述發現:
[](http://box.kancloud.cn/2015-09-15_55f7ef618d305.png)
執行檢查“EmpDept20View”的敘述可以發現這是一個有問題的View元件:
[](http://box.kancloud.cn/2015-09-15_55f7ef61cbb32.png)
## 7.2 取得View的相關資訊
MySQL數據庫在啟動以后,會有一個很特別的數據庫,名稱是“information_schema”,這個數據庫通常會稱為“系統資訊數據庫”。這個數據庫中有一個表格叫作“VIEWS”,它儲存所有MySQL數據庫中View元件的相關資訊,“VIEWS”表格有下列主要的字段:
| 字段名稱 | 型態 | 說明 |
| --- | --- | --- |
| TABLE_SCHEMA | varchar(64) | 數據庫名稱 |
| TABLE_NAME | varchar(64) | 表格名稱 |
| VIEW_DEFINITION | longtext | 算法定義與儲存的查詢敘述 |
| CHECK_OPTION | varchar(8) | 檢查范圍設定 |
| IS_UPDATABLE | varchar(3) | 是否可以執行資料維護 |
執行下列的敘述就可以查詢數據庫中的View元件資訊:
[](http://box.kancloud.cn/2015-09-15_55f7ef674bcf8.png)