轉自http://www.cnblogs.com/wangtao_20/archive/2011/02/24/1964276.htmlphp
1、使用視圖的理由是什麼? 1.安全性。通常是這樣作的:建立一個視圖,定義好該視圖所操做的數據。以後將用戶權限與視圖綁定。這樣的方式是使用到
了一個特性:grant語句能夠針對視圖進行授予權限。 2.查詢性能提升。
3.有靈活性的功能需求後,須要改動表的結構而致使工做量比較大。那麼可使用虛擬表的形式達到少修改的效果。html
這是在實際開發中比較有用的mysql
例子:假如由於某種須要,a表與b表須要進行合併起來組成一個新的表c。最後a表與b表都不會存在了。而因爲原來程序中編
寫sql分別是基於a表與b表查詢的,這就意味着須要從新編寫大量的sql(改爲向c表去操做數據)。而經過視圖就能夠作到不修
改。定義兩個視圖名字仍是原來的表名a和b。a、b視圖完成從c表中取出內容。
說明:使用這樣的解決方式,基於對視圖的細節瞭解越詳細越好。由於使用視圖仍是與使用表的語法上沒區別。好比視圖名a ,那麼查詢仍是"select * from a"。
4.複雜的查詢需求。能夠進行問題分解,而後將建立多個視圖獲取數據。將視圖聯合起來就能獲得須要的結果了。
視圖的工做機制:當調用視圖的時候,纔會執行視圖中的sql,進行取數據操做。視圖的內容沒有存儲,而是在視圖被引用的時候纔派生出數據。這樣不會佔用空間,因爲是即時引用,視圖的內容老是與真實表的內容是一致的。sql
視圖這樣設計有什麼好處?節省空間,內容是老是一致的話,那麼咱們不須要維護視圖的內容,維護好真實表的內容,就能夠保證視圖的完整性了。
2、經過更新視圖實現更新真實表數據庫
看到不少例子,更新視圖能夠更新真實表。緣由,我是這樣理解的:視圖並無保存內容。只是引用數據。那麼,更新視圖,其實就是以引用的方式操做了真實表 with check option:對視圖進行更新操做的時,須要檢查更新後的值是否仍是知足視圖公式定義的條件。通俗點,就是所更新的結果是否還會在視圖中存在。若是更新後的值不在視圖範圍內,就不容許更新若是建立視圖的時候,沒有加上with check option,更新視圖中的某項數據的話,mysql並不會進行有效性檢查。刪掉了就刪掉了。在視圖中將看不到了。
使用有效性檢查,實際意義是什麼?
視圖的實踐:從新組織表的需求 CREATE TABLE `result` (`MATH_NO` INT(10) NOT NULL unsigned AUTO_INCREMENT PRIMARY KEY, `TEAMNO` INT(10) NOT NULL, `PLAYERNO` INT(10) NOT NULL, `WON` VARCHAR(10) NOT NULL, `LOST` VARCAHR(10) NOT NULL, `CAPTAIN` INT(10) NOT NULL COMMIT '就是PLAYERNO的另外名字', `DIVISION` VARCHAR(10) NOT NULL ) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMIT='從新組的新表' AUTO_INCREMENT=1
針對每一個表建立一個視圖,將數據保存進去: CREATE VIEW teams(TEAMNO,PLAYERNO,DIVISION) AS SELECT DISTINCT TEAMNO,CAPTAIN,DIVISION FROM result
報錯:#1050 - Table 'teams' already exists
說明,由於視圖也是一種表,是虛擬表。不能與已有的表(視圖)出現重名
接下來,刪掉表teams,再執行建立視圖的代碼。
將視圖當作與表同樣的東西,更加容易理解使用規則。下面這樣對比也許使本身更好理解:
1.在使用視圖的時候,就是與使用表的語法同樣的。 2.建立視圖的時候,該視圖的名字若是與已經存在表重名的話,那麼會報錯,不容許建立。視圖就是一種特殊的表
3.建立視圖的時候,能夠這樣使用CREATE VIEW teams(TEAMNO,PLAYERNO,DIVISION),能夠定義視圖表的結構。 4.在phpmyadmin中。左邊的表列表中將視圖與表列在了一塊兒。只有經過右側的狀態"View:teams"能夠知道該表是視圖表。
視圖在mysql中的內部管理機制:
視圖的記錄都保存在information_schema數據庫中的一個叫views的表中。具體某個視圖的定義代碼以及屬於哪一個數據庫等信息能夠從裏面看到理解視圖的兩種工做機制:
語句:select * from teams
針對上面語句,總結幾個知識點 1.確認是視圖的過程:teams也能夠是表名。因爲表與視圖的物理機制不一樣。視圖自己是不存儲內容的。因此,在使用sql的 時候,mysql是怎麼知道teams是一個視圖仍是表。是由於有一個查看目錄的例程在作這件事。安全
2.mysql對處理視圖的兩種方法:替代方式和具體化方式。 替換方式理解,視圖名直接使用視圖的公式替換掉了。針對上面視圖teams,mysql會使用該視圖的公式進行替換,視圖公式合併到了select中。結果就是變成了以下sql語句: select * from (SELECT DISTINCT TEAMNO,CAPTAIN,DIVISION FROM result)。也就是最後提交給mysql處理該sql語句。
具體化方式理解,mysql先獲得了視圖執行的結果,該結果造成一箇中間結果暫時存在內存中。以後,外面的select語句就調
用了這些中間結果(臨時表)。
看起來都是要獲得結果,形式上有區別,好像沒體會到本質上的區別。兩種方式又有什麼樣的不一樣呢?
替換方式,將視圖公式替換後,當成一個總體sql進行處理了。具體化方式,先處理視圖結果,後處理外面的查詢需求。 替換方式能夠總結爲,先準備,後執行。 具體化方式總結理解爲,分開處理。
哪一種方式好?不知道。mysql會本身肯定使用哪一種方式進行處理的。本身在定義視圖的時候也能夠指定使用何種方式。像這樣
使用:
CREATE ALGORITHM=merge VIEW teams as SELECT DISTINCT TEAMNO,CAPTAIN,DIVISION FROM result
ALGORITHM有三個參數分別是:merge、TEMPTABLE、UNDEFINED
看mysql手冊中提到,替換與具體化的方式的各自適用之處,能夠這樣理解: 由於臨時表中的數據不可更新。因此,若是使用參數是TEMPTABLE,沒法進行更新。 當你的參數定義是UNDEFINED(沒有定義ALGORITHM參數)。mysql更傾向於選擇合併方式。是由於它更加有效。性能