mysql檢視學習總結

wulantian發表於2015-01-23

mysql檢視學習總結

儲存,學習,共享!

一、使用檢視的理由是什麼?
1.安全性。一般是這樣做的:建立一個檢視,定義好該檢視所操作的資料。之後將使用者許可權與檢視繫結。這樣的方式是使用到

了一個特性:grant語句可以針對檢視進行授予許可權。
2.查詢效能提高。

3.有靈活性的功能需求後,需要改動表的結構而導致工作量比較大。那麼可以使用虛擬表的形式達到少修改的效果。

這是在實際開發中比較有用的


例子:假如因為某種需要,a表與b表需要進行合併起來組成一個新的表c。最後a表與b表都不會存在了。而由於原來程式中編

寫sql分別是基於a表與b表查詢的,這就意味著需要重新編寫大量的sql(改成向c表去運算元據)。而通過檢視就可以做到不修

改。定義兩個檢視名字還是原來的表名a和b。a、b檢視完成從c表中取出內容。

說明:使用這樣的解決方式,基於對檢視的細節瞭解越詳細越好。因為使用檢視還是與使用表的語法上沒區別。比如檢視名a
,那麼查詢還是"select * from a"。

4.複雜的查詢需求。可以進行問題分解,然後將建立多個檢視獲取資料。將檢視聯合起來就能得到需要的結果了。



檢視的工作機制:當呼叫檢視的時候,才會執行檢視中的sql,進行取資料操作。檢視的內容沒有儲存,而是在檢視被引用的時候才派生出資料。這樣不會佔用空間,由於是即時引用,檢視的內容總是與真實表的內容是一致的。

檢視這樣設計有什麼好處?節省空間,內容是總是一致的話,那麼我們不需要維護檢視的內容,維護好真實表的內容,就可以保證檢視的完整性了。

二、通過更新檢視實現更新真實表


看到很多例子,更新檢視可以更新真實表。原因,我是這樣理解的:檢視並沒有儲存內容。只是引用資料。那麼,更新檢視,其實就是以引用的方式操作了真實表
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更傾向於選擇合併方式。是因為它更加有效。

相關文章