勿以惡小而爲之,勿以善小而不爲--------------------------劉備
上一章簡單介紹了 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;
視圖是非常重要的,老蝴蝶建議一定要掌握其常見用法。
謝謝!!!