快速入門:使用ecshop 的goods表,查詢平均價格前三高的欄目。
傳統方式:
select cat_id,avg(shop_price) as aprice from goods
group by cat_id
order by aprice desc limit 3;
新的方式:利用建立檢視
#建立檢視:
create view v1 as
select cat_id,avg(shop_price) as aprice from goods;
#檢視檢視:
Show tables;
#檢視檢視列:
Desc 檢視名
#檢視檢視建立:
Show create view 檢視名
#刪除檢視:
Drop view 檢視名
檢視的好處:
1. 簡化查詢。
2. 許可權控制。
3. 分表查詢.
4. 可維護性好。、
A .簡化查詢,上面的例子用檢視實現的程式碼:
建立檢視表
Create view v1 as
Select gooods_id,cat_id,goods_name,avg(shop_price) as aprice from esc_goods group by cat_id;
#查詢檢視表
Select *from v1 order by aprice limit 3;
B 許可權控制,假設有如下表,由小劉來維護,需要他進行開發和管理銷售軟體,但又不能讓其看到成本價,該怎麼做?
編號產品名稱市場價成本價單位品牌
1黃金446200元/克周大福
2鉑金375.94192元/克周大福
3金條456.87185.35元/克周大生
4飾品461203.58元/克周大生
#演示如何通過檢視來控制許可權
#建立珠寶表
create table jewelry(
id int unsigned not null auto_increment primary key,
name varchar(20) not null,
price decimal(10,2) not null,
cost decimal(10,2) not null,
unit varchar(20) not null,
brand varchar(30) not null
);
#插入幾條記錄
insert into jewelry(name,price,cost,unit,brand) values('黃金',446,200,'元/克','周大福');
insert into jewelry(name,price,cost,unit,brand) values('鉑金',375.94,192,'元/克','周大福');
insert into jewelry(name,price,cost,unit,brand) values('金條',456.87,185.35,'元/克','周大生');
insert into jewelry(name,price,cost,unit,brand) values('飾品',461,203.58,'元/克','周大生');
#建立一個檢視
#新建使用者,登入MySQL
mysql> insert into user(host,user,password,ssl_cipher,x509_issuer,x509_subject) values('localhost'
test',password('123'),'','','');
#重新整理系統許可權表
mysql> flush privileges;
#為使用者授權,要使用root賬戶,針對某個檢視建立許可權(資料庫名.檢視名)
grant select,insert,update,delete on wcp.vj to test@localhost;
#刪除使用者
C 分表查詢,加快查詢速度。假設現在有一個海量資料表,比如QQ賬戶表,使用者反映登入時間太長,有沒有辦法將其優化一下?
分表:
可以按qq號碼取餘的方式將qq使用者表分成10張表,
Qq1,qq2,qq3,qq4,qq5,
如何查詢?
10003 %10 = 3
Create view vq as
Slect * from qq1 union select * from qq2
D 維護性好,小明在公司做網站開發和維護工作,因為業務的變化,資料庫中有兩張表a和b,現在需要組合成c表,你能幫他出出主意嗎?
A表
B表
C表
可以利用檢視,先把表A和表B聯合成一張表C,然後從c表分別建立原來 表A的檢視和表B的檢視 ,這樣程式只需要稍微改下,原來的查詢等語句照樣使用。
深入理解檢視-檢視的演算法及其與表的關係
1. 檢視和表是什麼關係?
檢視是一張虛擬的表,並不是物理上存在的,只不過我們可以將其作為表來使用。
使用檢視可以節省空間。
2. 檢視是如何工作的?
在使用檢視的時候,引用對應的表,查詢得到這個結果。
3. 檢視和表之間的操作會影響對方嗎?
編號名稱價格作業系統品牌
1iphone55999iosApple
2iphone4s4430iosApple
3htc 328w2930androidHTC
4htc G212250androidHTC
5htc one s2500androidHTC
6lumia 9204590wp8Nokia
7lumia 8002900wp7Nokia
8nokia N9 2300MeeGoNokia
9Galaxy 33480androidsamsung
#建立phone表
create table phone(
id int unsigned not null auto_increment primary key,
name varchar(30) not null,
price decimal(7,2) not null,
os varchar(30) not null,
brand varchar(30) not null
);
#插入八條記錄
insert into phone(name,price,os,brand) values('iphone5',5999,'ios','Apple');
insert into phone(name,price,os,brand) values('iphone4s',4430,'ios','Apple');
insert into phone(name,price,os,brand) values('htc328w',2930,'android','HTC');
insert into phone(name,price,os,brand) values('htc G21',2250,'android','HTC');
insert into phone(name,price,os,brand) values('htc one s',2500,'android','HTC');
insert into phone(name,price,os,brand) values('lumia920',4590,'wp8','Nokia');
insert into phone(name,price,os,brand) values('lumia800',2900,'wp7','Nokia');
insert into phone(name,price,os,brand) values('nokia n9',2300,'meego','Nokia');
#建立一個檢視vphone1
mysql> create view vp1 as select name,price,brand from phone;
#對錶更新,看其對檢視的影響
結論:表的更新會直接影響到檢視。
#檢視檢視
#對檢視更新,看其對錶的影響
update vp1 set price = price - 500;
結論:改變檢視是可以改變表的。但是不是總是能改變,只有在檢視和原表一一對應的情況下才能通過檢視改變表。
#再建立一個檢視,vphone2
mysql> create view vp2 as
-> select brand,avg(price) as aprice from phone
-> group by brand;
#檢視檢視
#更新檢視vphone2
mysql> update vp2 set aprice = aprice + 500;
ERROR 1288 (HY000): The target table vp2 of the UPDATE is not updatable
結論:但是不是總是能改變,只有在檢視和原表一一對應的情況下才能通過檢視改變表。
#向檢視vphone1中插入記錄,
mysql> insert into vp1 values('galaxy '3470','samsung','android');
ERROR 1423 (HY000): Field of view 'wcp.vp1' underlying table doesn't have a default value
對於在檢視中沒有出現的列,而在表中有沒有預設值,則此時插入會失敗。
#更改表結構
mysql> alter table phone modify os varchar(30) not null default '';
#再向檢視vphone1中插入記錄
mysql> insert into vp1 values('galaxy '3470','samsung','android');
4. 檢視使用注意事項
a. 檢視也是一種表,是虛擬表,或者說表和檢視共享資料庫中相同的名稱空間,不能與已有的表(檢視)出現重名。
b. 檢視屬於資料庫。在預設情況下,將在當前資料庫建立新檢視。
檢視的演算法
1. 使用檢視來實現查詢每個欄目下最貴的商品,該怎麼做?
原先做法:
mysql> select goods_id,goods_name,cat_id,shop_price from (
-> select goods_id,goods_name,cat_id,shop_price from goods
-> order by cat_id,shop_price desc) as temp
-> group by cat_id;
使用檢視來實現:
mysql> create view vec as
-> select goods_id,goods_name,cat_id,shop_price from goods
-> order by cat_id,shop_price desc;
mysql> select * from vec group by cat_id;
結果不對,why?
把建立檢視和查詢檢視的語句合併到一起。
select * from select goods_id,goods_name,cat_id,shop_price from goods group by cat_id order by cat_id,shop_price desc;
這樣又回到我們錯誤的老路上。
原因,就是因為使用的是merge演算法,
檢視的三種演算法(algorithm)
模式說明備註
merge合併,在執行檢視的時候,將查詢檢視語句和建立檢視語句合併到一起,然後執行。預設
temptable臨時表,在執行查詢檢視語句時,首先執行建立檢視語句,並將其作為一個臨時表,接著讓查詢檢視的語句查詢。
undefined未定義,自動選擇,
改變檢視的演算法:
Create algorithm = temptable view 檢視名 as
mysql> create algorithm=temptable view vec as
-> select goods_id,goods_name,cat_id,shop_price from goods
-> order by cat_id,shop_price desc;