MySQL的視圖(二十二)

勿以惡小而爲之,勿以善小而不爲--------------------------劉備

上一章簡單介紹了 MySQL合併查詢結果(二十一),如果沒有看過,請觀看上一章

一 . 視圖

一.一 視圖的出現

前面講解了各種查詢和子查詢,如果要進行一個複雜功能的查詢,那麼就可能需要寫很長很長的一個sql, 在代碼中將這些sql進行硬編碼進去,不便於後期維護和複用。 有沒有一種技術,可以像使用表查詢那樣簡單 (select * from 表名 ), 將那個很長很長的sql的查詢結果封裝到一個獨特的表裏面呢? 以後在查詢的時候,直接查詢那個獨特的表即可? 實際上,數據庫提供了這麼一個技術, 這個技術叫做 視圖 (view) .

視圖(view) 和 表(table) 是有區別的。 表中的數據是一個真正存在的,存儲於物理結構中, 而視圖中的數據是虛擬的,
並不真實存在。

視圖,常常適用於用於多個表連接查詢之間的結果。

一.二 視圖的優點

一.二.一 簡單化

看到的,就是查詢出來的。 直接 select * from 視圖 即可, 並不需要向以前那樣,寫一個很長的sql語句(sql語句中,包括where,分組,排序等)

一.二.二 安全性

視圖中只能查詢和修改視圖使用者所能看到的數據,不能維護其看不到的數據。 也就是, 表使用者和視圖使用者,兩個人的權限是不一樣的, 從而保證了數據的安全性。

如在 user 表裏面,存在以下數據:

	select * from user;

有圖片。

共九個數據。

那麼, 表使用者可以看到這九個員工, 同樣,也可以維護 這九個員工的信息。

如果將

	select * from user where id=1;

有圖片

這一條數據,封裝成視圖, 那麼,視圖使用者只能看到這一個姓名爲 ‘兩個蝴蝶飛’ 的數據,也只能維護這一個員工的信息, 不能維護他看不到的,如 ‘嶽澤霖’ 等這些數據。 從而,保證了重要數據的安全性。

如 員工工資數據,只有財務部門可以看,人事部門是沒有辦法查看的。

一.二.三 邏輯數據獨立性

可以屏蔽真實表的表結構信息。

如 查詢真實表的話, select * from user, 那麼用戶就可以看到,這個表 user 裏面有 id,name,sex,birthday,age,deptId 六個字段。

如將 :

	 select id,name from user ;

的查詢結果封裝成一個視圖,如視圖 v_user 的話, 那麼在查詢 視圖 v_user 時,只會顯示 id,name 兩個字段, 從而避免了真實表 user 的數據結構。

如將

	 select a.id as uId,a.name as uName,d.id as dId,d.name as dName from user a
	  left join dept d on a.deptId=d.id; 

的查詢結果封裝成一個視圖, 如視圖 v_user_dept 的話, 那麼在查詢 視圖 v_user_dept 時,只會顯示 員工編號,員工名稱 ,部門編號,部門名稱 四個字段, 從而屏蔽了真實 user 表和 真實 dept 表中的字段。

一.三 視圖的操作

視圖,通常有以下幾種操作

操作指令 代碼
創建視圖 create view 視圖名 as sql查詢
查看視圖 describe 視圖名 或者 show create view 視圖名
修改視圖 create or replace view 視圖 as sql查詢
使用視圖 正常表 table 的使用
刪除視圖 drop view [if exists] 視圖名
視圖條件限制 with check option

下面,老蝴蝶 分別對每一種操作進行講解。

視圖,仍然使用的是 user 表和 dept 表進行講解。

	use yuejl;
	select * from user;
	select * from dept;

有圖片

二. 創建視圖 create view view_name

二.一 創建的命令

創建視圖的完整命令是:

	create [or replace] [algorithm={undefined|megre|temptable}]
	view view_name [{column_list}]
	as select_statement
	[with {cascaded|local} check option]

通常,會簡寫成:

	create [or replace]
	view view_name [{column_list}]
	as select_statement 

create 表示創建, or replace 表示 替換。 連用的話, create or replace 表示,如果存在這個視圖名,就替換,
如果不存在,就創建。

其中,{column_list} 常常會省略,省略時,表示 視圖中的字段名稱 與 select_statement 中的字段名稱一致。

其中,創建視圖,可以在單表上,也可以在多表上。

二.二 單個表省略字段創建視圖

如,查詢員工的id,name,age 和 id和age的積 的值。

查詢語句爲:

	select id,name,age,id*age from user;

有圖片

那麼, 創建 單表視圖, 如 v_user1 就是:

	create view v_user1
	as select id,name,age,id*age from user;

有圖片

查詢 視圖 v_user1, 就像查詢表 那麼操作

	select * from v_user1;

有圖片

其中, 視圖的字段列表,就是查詢的語句的字段列表。

二.三 單個表重新定義字段 創建視圖

將視圖的字段列表,重新定義, 不用原先的 查詢表中的字段, 需要用到 [{column_list}]

	create view v_user2 (nId,nName,nAge,nIdAge)
	as select id,name,age,id*age from user;

有圖片

再次查詢時:

	select * from v_user2;

有圖片

發現,視圖字段就變成了新定義的字段列表了。

二.四 多個表創建視圖

如,查詢每個員工的編號,姓名,部門編號和部門的名稱。

查詢語句爲:

	 select a.id as uId,a.name as uName,d.id as dId,d.name as dName from user a
	  left join dept d on a.deptId=d.id; 

有圖片

創建視圖 v_user_dept

	create view v_user_dept (uId,uName,dId,dName)
	as (select a.id as uId,a.name as uName,d.id as dId,d.name as dName from user a 
		left join dept d on a.deptId=d.id) ;

有圖片

查詢視圖

	select * from v_user_dept;

有圖片

會發現, 視圖的查詢,遠比表連接查詢,更簡單,也更易複用。

三. 查看視圖

如何像查看 表結構 那樣, 查看視圖結構呢?

三.一 describe view_name

如 查詢剛纔創建的 v_user1 視圖

	describe v_user1;

有圖片

與 describe 表名 查詢出來的結構一致。

其中,也可以用其簡寫的形式, desc view_name

	desc v_user1;

有圖片

三.二 show create view view_name

如 查詢剛纔創建的 v_user2 視圖

	show create view v_user2 \G

有圖片

與 show create table table_name 一致。

三.三 show table status like ‘視圖名’

查看 視圖結構的詳細信息

如 查看 視圖 v_user1

	show table status like 'v_user1' \G

有圖片

comment 爲 view 表示,是視圖

如果是表的話, comment 顯示的是 空字符串

	show table status like 'user' \G

有圖片

三.四 information_schema 數據庫下的 views 表

如 查詢一下 v_user1 視圖

	select * from information_schema.views t where t.table_name='v_user1' \G

有圖片

information_schema.views, 表示去查詢 information_schema 數據庫下的 views 表(注意,此時仍然在 yuejl數據庫中)

一般 使用 describe(desc) 視圖名 進行查詢視圖的相關信息。

四. 修改視圖

修改已經存在的視圖,有兩種方式,一種是 create or replace, 另外一種是用 alter .

四.一 create or replace 重新創建視圖

修改視圖,用的是 or replace ,會重新創建一個新的視圖。

如 修改 視圖 v_user1, 改變 查詢 name 和 age 的視圖。 不能改變視圖名稱,只改變查詢結果。

	create or replace view v_user1(name,age)
	as (select name,age from user) ;

有圖片

查詢一下數據:

	select * from v_user1;

有圖片

會發現,視圖 v_user1 被修改了。

注意,此時如果視圖名稱不存在,那麼將會創建一個新視圖。

四.二 alter view view_name 重新創建視圖

修改視圖,而不是 存在時修改,不存在時創建,那麼可以直接使用 alter 進行修改

如 修改 v_user2 ,讓其只查詢 id 和 name 兩個列。

	alter view v_user2 (id,name)
	as (select id,name from user);

有圖片

將 create or replace 替換成 alter .

重新查詢 v_user2 的話:

	select * from v_user2;

在這裏插入圖片描述

問題1: 如果 alter 修改的是一個不存在的視圖, 如 v_user100 時,會出現什麼情況呢?

	alter view v_user100 (id,name)
	as (select id,name from user);

有圖片

ERROR 1146 (42S02): Table ‘yuejl.v_user100’ doesn’t exist

會報錯,提示視圖不存在。

五. 使用/更新 視圖

視圖是一個虛擬表,沒有存儲數據,所以對視圖數據的更新,實際上都轉移到對基本表的更新上了。但是,不建議對視圖進行更新操作, 只提倡查詢。

五.一 查詢數據

如 查詢視圖 v_user2

	select * from v_user2;

有圖片

v_user2 裏面,有兩個字段, id 和 name.

五.二 插入數據

當前, user 表 還是9條數據, 沒有發生改變。

	select * from user;

有圖片。

往視圖 v_user2 裏面插入一條數據, id 是10, 名稱爲 新員工5.

	insert into v_user2(id,name) values(10,'新員工5');

有圖片

這個時候,重新查看一下 v_user2 視圖數據

	select * from v_user2;

有圖片

查看一下基本表 user中的數據

	select * from user;

有圖片

可以看出,正常的插入到視圖(準確說是基本表)裏面了.

五.三 更新數據

如將 視圖 v_user2 裏面的 id=10 新插入的那個數據 的員工名稱 改變 ‘我是新來的員工5’

	update v_user2 set name='我是新來的員工5' where id=10;

有圖片

查看一下基本表 user 中的數據

	select * from user;

有圖片

五.四 刪除數據

如將 視圖 v_user2 裏面的那條 id=10 的數據刪除。

	delete from v_user2 where id=10;

有圖片

再重新查詢一下 user 表的數據

	select * from user;

有圖片

五.五 約束性視圖

在實際開發生活中,是不允許你通過更新視圖進行改變基本表的數據, 所以常常會增加一些限制。

如 創建一個新視圖 v_user3, 裏面有 id 和 name 兩個字段,但是有限制。

	create or replace 
	view v_user3 (id,name)
	as (select id,name from user where id<20)
	with check option;

有圖片

從表裏面查詢出來的數據,必須要保證 id<20.

那麼,此時 查詢一下視圖:

	select * from v_user3;

有圖片

如果此時,往視圖裏面 添加 一條 id=100 的新數據(100>20)

	insert into v_user3 (id,name) values(100,'新約束員工');

有圖片

ERROR 1369 (HY000): CHECK OPTION failed ‘yuejl.v_user3’

會發現,不能插入進去 。

如果此時,往視圖裏面添加 一條 id=11 的新數據 (11<20)

	insert into v_user3 (id,name) values(11,'新約束員工');

有圖片

可以正確地插入

重新查詢一下數據:

	select * from user;

有圖片

添加 with check option 之後,維護後的數據不能確定視圖的完整性。

六. 刪除視圖

命令:

	drop [if exists] view view_name;

如刪除 視圖 v_user3

	drop view v_user3;

有圖片

再次查詢視圖 v_user3的話:

	select * from v_user3;

有圖片

如果刪除一個不存在的視圖, 那麼也會報錯的。

刪除視圖,支持同時刪除多個視圖, 如再刪除 v_user1和 v_user2

	drop view v_user1,v_user2;

有圖片

視圖是非常重要的,老蝴蝶建議一定要掌握其常見用法。

謝謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章