MySQL之檢視學習
MYSQL---檢視
1、概述:
檢視是從一個或者多個表中匯出的,檢視的行為與表非常類似,但檢視是一個虛擬表.在檢視中使用者可以使用SELECT語句查詢資料,以及使用INSERT、UPDATE和DELETE修改記錄。從MYSQL5.0開始可以使用檢視,檢視可以使使用者操作方便,而且可以保障資料庫系統的安全。
1.1、檢視的含義
檢視是一個虛擬表,是從資料庫中一個或多個表中匯出來的表。檢視還可以從已經存在的檢視的基礎上定義。
檢視一經定義便儲存在資料庫中,與其相對應的資料並沒有像表那樣在資料庫中再儲存一份,通過檢視看到的資料只是存放在基本表中的資料。對檢視的操作與對錶的操作一樣,可以對其進行查詢、修改和刪除。當對通過檢視看到的資料進行修改時,相應的基本表的資料也要發生變化;同時,若基本表的資料發生變化,則這種變化也可以自動地反映到檢視中。
下面有個student表和stu_info表,在student表中包含了學生的id號和姓名,stu_info表中包含了學生的id號、班級和家庭住址,而現在公佈分班資訊,只需要id號、姓名和班級,這該如何解決?
表設計如下:
CREATE TABLE student ( s_id INT, name VARCHAR(40) ); CREATE TABLE stu_info( s_id INT, glass VARCHAR(40), addr VARCHAR(90) );
通過DESC+表名命令可以查看錶的設計,可以獲得欄位、欄位的定義、是否為主鍵、是否為空、預設值和擴充套件資訊。
檢視提供了一個很好的解決方法,建立檢視的資訊來自表的部分資訊,只取需要的資訊。這樣既能滿足要求也不破壞表原來的結構。
1.2、檢視的作用
與直接從資料表中讀取相比,檢視有以下優點:
1.簡單化
看到的就是需要的。檢視不僅可以簡化使用者對資料的理解,也可以簡化他們的操作。那些被經常使用查詢可以被定義為檢視,從而使得使用者不必為以後的操作每次指定全部的條件。
2.安全性
通過檢視使用者只能查詢和修改他們所能見到的資料。資料庫中的其他資料則既看不見也取不到。資料庫授權命令可以使每個使用者對資料庫的檢索限制到特定的資料庫物件上,但不能被授權到資料庫特定的行和特定的列上。通過檢視,使用者可以被限制在資料的不同子集上;
-
使用許可權可被限制在基表的行的子集上。
-
使用許可權可被限制在基表的列的子集上。
-
使用許可權可被限制在基表的行和列的子集上。
-
使用許可權可被限制在多個基表的連線所限定的行上。
-
使用許可權可被限制在基表中的資料的統計彙總上。
-
使用許可權可被限制在另一檢視的一個子集上,或是一些檢視和基表合併後的子集上。
3.邏輯資料的獨立性
檢視可幫助使用者遮蔽真實表結構變化帶來的額影響。
2、建立檢視
檢視中包含了SELECT 查詢的結果,因此檢視的建立基於SELECT語句和已存在的資料表,檢視可以建立在一張表上,也可以建立在多張表上.
2.1、建立檢視的語法形式
建立檢視使用CREATE VIEW 語句,基本語法格式如下:
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS SELECT_statemment [WITH [CASCADED | LOCAL] CHECK OPTION]
其中,CREATE表示建立新的檢視;REPLACE表示替換已經建立的檢視;ALGORITHM表示檢視選擇的演算法;view_name為 檢視的名稱,column_list為屬性列;SELECT_statement表示SELECT語句;WITH[CASCADED|LOCAL]CHECKOPTION引數表示檢視在更新時保證在檢視的許可權範圍內。
ALGORITHM的取值有3個,分別是UNDEFINED|MERGE|TEMPTABLE,UNDEFINED表示MYSQL將自動選擇演算法;MERGE表示將使用的檢視語句與檢視定義合併起來,使得檢視定義的某一部分取代語句對應的部分;TEMPTABLE表示將檢視的結果存入臨時表,然後用臨時表來執行語句。
CASCADED與LOCAL為可選引數,CASCADED為預設值,表示更新檢視時要滿足所有相關檢視的和表的條件;LOCAL表示更新檢視時滿足該檢視本身定義的條件即可。
該語句要求具有針對檢視的CREATE VIEW許可權,以及針對由SELECT語句選擇的每一列上的某些許可權。對於在SELECT語句中其他地方使用到的列,必須具有SELECT許可權。如果還有OR REPLACE子句,必須在檢視上具有DROP許可權。
檢視屬於資料庫。在預設情況下,將在當前資料庫建立新檢視。要想在給定資料庫中明確建立檢視,建立時應將名稱指定為db_name.view_name。
2.2、在單表建立檢視
MYSQL可以在單個數據表上建立檢視
例1:在t表上建立一個名為view_t的檢視。
首先建立基本表並插入資料,語句如下:
create table t (quantity int,price int); insert into t values(3,50);
建立檢視語句如下:
create view view_t as select quantity,price,quantity * price from t;
語句執行如下:
mysql> create view view_t as select quantity,price,quantity * price from t; Query OK, 0 rows affected (0.59 sec) mysql> select * from view_t; +----------+-------+------------------+ | quantity | price | quantity * price | +----------+-------+------------------+ | 3 | 50 | 150 | +----------+-------+------------------+ 1 row in set (0.04 sec)
預設情況下建立的檢視和基本表的欄位是一樣的,也可以通過指定檢視欄位的名稱來建立檢視。
例2:在t表格上建立一個 名為view_t2的檢視,程式碼如下:
mysql> create view view_t2(qty,price,total) as select quantity,price,quantity * price from t; Query OK, 0 rows affected (0.06 sec) mysql> select * from view_t2; +------+-------+-------+ | qty | price | total | +------+-------+-------+ | 3 | 50 | 150 | +------+-------+-------+ 1 row in set (0.00 sec)
可以看到,view_t2和view_t兩個檢視中欄位名稱不同,但資料卻是相同的。因此,在使用檢視的時候,可能使用者根本就不需要了解基本表的結構,更接觸不到實際表中的資料,從而保證了資料庫的安全。
2.3、在多表上建立檢視
MYSQL中也可以在兩個或者兩個以上的表上建立檢視,可以使用CREATE VIEW語句實現。
例1:在表student和表stu_info上建立檢視stu_glass,程式碼如下:
首先向兩個表中插入資料,輸入語句如下:
mysql> insert into student values(1,'wanglin1'),(2,'gaoli'),(3,'zhanghai'); Query OK, 3 rows affected (0.25 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> insert into stu_info values(1,'wuban','henan'),(2,'liuban','hebei'),(3,'qiban','shandong'); Query OK, 3 rows affected (0.15 sec) Records: 3 Duplicates: 0 Warnings: 0
建立檢視stu_class,語句如下:
create view stu_glass (id ,name ,glass) as select student.s_id,student.name,stu_info.glass from student,stu_info where student.s_id=stu_info.s_id;
程式碼的執行如下:
mysql> create view stu_glass (id ,name ,glass) as select student.s_id,student.name,stu_info.glass -> from student,stu_info where student.s_id=stu_info.s_id; Query OK, 0 rows affected (0.08 sec) mysql> select * from stu_glass; +------+----------+--------+ | id | name | glass | +------+----------+--------+ | 1 | wanglin1 | wuban | | 2 | gaoli | liuban | | 3 | zhanghai | qiban | +------+----------+--------+ 3 rows in set (0.00 sec)
這個例子就解決了剛開始提出的問題,通過這個檢視可以很好地保護基礎表中的資料。這個檢視中的資訊很簡單,只包含了id、姓名和班級,id欄位對應student表中的s_id欄位,name欄位對應student表中的name欄位,glass欄位對應stu_info表中的glass欄位。
3、檢視檢視
檢視檢視是檢視資料庫中已存在的檢視的定義。檢視檢視必須要有show view的許可權,MYSQL資料庫下的user表中 儲存著這個資訊。檢視檢視的方法包括:describe、show table status 和show create view。
3.1、使用describe語句檢視檢視基本資訊
describe可以用來檢視檢視,具體語法如下:
describe 檢視名
例1:通過describe語句檢視檢視view_t的定義,程式碼如下:
describe view_t
程式碼執行如下:
mysql> describe view_t; +------------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------+------+-----+---------+-------+ | quantity | int(11) | YES | | NULL | | | price | int(11) | YES | | NULL | | | quantity * price | bigint(21) | YES | | NULL | | +------------------+------------+------+-----+---------+-------+ 3 rows in set (0.24 sec)
結果顯示出了檢視的欄位定義、欄位的資料型別、是否為空、是否為主/外來鍵、預設值和額外資訊。
describe 一般情況下都簡寫成desc,輸入這個命令的執行結果和輸入describe的執行結果是一樣的。
3.2、使用show table status語句檢視檢視基本資訊
檢視檢視的資訊可以通過show table status的語法,具體的語法如下:
show table status like '檢視名';
例1:通過下面的例子來學習使用show table status 命令檢視檢視資訊。
show table status like 'view_t' \G
執行結果如下:
mysql> show table status like 'view_t' \G *************************** 1. row *************************** Name: view_t Engine: NULL Version: NULL Row_format: NULL Rows: 0 Avg_row_length: 0 Data_length: 0 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: NULL Create_time: 2019-06-16 21:06:38 Update_time: NULL Check_time: NULL Collation: NULL Checksum: NULL Create_options: NULL Comment: VIEW 1 row in set (0.00 sec)
執行結果顯示,表的說明Comment的值為VIEW說明該表為檢視,其他的資訊為null,說明這是一個虛表。用同樣的語句來檢視一下資料表t的資訊,執行結果如下:
mysql> show table status like 't' \G *************************** 1. row *************************** Name: t Engine: InnoDB Version: 10 Row_format: Dynamic Rows: 1 Avg_row_length: 16384 Data_length: 16384 Max_data_length: 0 Index_length: 0 Data_free: 0 Auto_increment: NULL Create_time: 2019-06-16 20:06:20 Update_time: 2019-06-16 20:06:43 Check_time: NULL Collation: utf8_general_ci Checksum: NULL Create_options: Comment: 1 row in set (0.11 sec)
從查詢的結果來看,這裡的資訊包含了儲存引擎、建立時間等,Comment 資訊為空,這就是檢視和表的區別。
3.3、使用show create view 語句檢視檢視詳細資訊
使用show create view 語句可以檢視檢視的詳細定義,語法如下:
show create view 檢視名
例1:show create view 檢視檢視的詳細定義,程式碼如下:
show create view view_t \G
執行結果如下:
mysql> show create view view_t \G *************************** 1. row *************************** View: view_t Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `view_t` AS select `t`.`quantity` AS `quantity`,`t`.`price` AS `price`,(`t`.`quantity` * `t`.`price`) AS `quantity * price` from `t` character_set_client: gbk collation_connection: gbk_chinese_ci 1 row in set (0.00 sec)
執行結果顯示檢視的名稱、建立檢視的語句等資訊。
3.4、在views表中檢視檢視詳細資訊
在MYSQL中,information_schema資料庫下的views表中儲存了所有檢視的定義。通過對views表的查詢,可以檢視資料庫中所有檢視的詳細資訊,查詢語句如下:
select * from information_schema.views\G
例1:在views表中檢視檢視的詳細定義,程式碼如下:
*************************** 101. row *************************** TABLE_CATALOG: def TABLE_SCHEMA: mysql_study TABLE_NAME: view_t VIEW_DEFINITION: select `mysql_study`.`t`.`quantity` AS `quantity`,`mysql_study`.`t`.`price` AS `price`,(`mysql_study`.`t`.`quantity` * `mysql_study`.`t`.`price`) AS `quantity * price` from `mysql_study`.`t` CHECK_OPTION: NONE IS_UPDATABLE: YES DEFINER: root@localhost SECURITY_TYPE: DEFINER CHARACTER_SET_CLIENT: gbk COLLATION_CONNECTION: gbk_chinese_ci *************************** 102. row *************************** TABLE_CATALOG: def TABLE_SCHEMA: mysql_study TABLE_NAME: view_t2 VIEW_DEFINITION: select `mysql_study`.`t`.`quantity` AS `quantity`,`mysql_study`.`t`.`price` AS `price`,(`mysql_study`.`t`.`quantity` * `mysql_study`.`t`.`price`) AS `quantity * price` from `mysql_study`.`t` CHECK_OPTION: NONE IS_UPDATABLE: YES DEFINER: root@localhost SECURITY_TYPE: DEFINER CHARACTER_SET_CLIENT: gbk COLLATION_CONNECTION: gbk_chinese_ci *************************** 103. row *************************** TABLE_CATALOG: def TABLE_SCHEMA: mysql_study TABLE_NAME: stu_glass VIEW_DEFINITION: select `mysql_study`.`student`.`s_id` AS `s_id`,`mysql_study`.`student`.`name` AS `name`,`mysql_study`.`stu_info`.`glass` AS `glass` from `mysql_study`.`student` join `mysql_study`.`stu_info` where (`mysql_study`.`student`.`s_id` = `mysql_study`.`stu_info`.`s_id`) CHECK_OPTION: NONE IS_UPDATABLE: YES DEFINER: root@localhost SECURITY_TYPE: DEFINER CHARACTER_SET_CLIENT: gbk COLLATION_CONNECTION: gbk_chinese_ci 103 rows in set (1.46 sec)
查詢的結果顯示當前以及定義的所有檢視的詳細資訊。
4、修改檢視
修改檢視是指修改資料庫中存在的檢視,當基本表的某些欄位發生變化的時候,可以通過修改檢視來保持與基本表的一致性。MYSQL中通過create or replace view 語句和alter語句來修改檢視。
4.1、使用create or replace view 語句修改試圖
MYSQL中如果要修改檢視,使用create or replace view 語句,語法如下:
create [or replace] [algorithm = {undefined | merge | temptable}] view view_name [(column_list)] as select statement [with [cascaded | local] check option]
可以看到,修改檢視的語句和建立檢視的語句是完全一樣的。當檢視已經存在時,修改語句對檢視進行修改;當檢視不存在時,建立檢視。
例1:修改檢視view_t,程式碼如下:
create or replace view view_t as select * from t;
首先通過desc檢視一下更改之前的檢視,以便與更改之後的檢視進行對比。執行結果如下:
mysql> desc view_t; +------------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------+------+-----+---------+-------+ | quantity | int(11) | YES | | NULL | | | price | int(11) | YES | | NULL | | | quantity * price | bigint(21) | YES | | NULL | | +------------------+------------+------+-----+---------+-------+ 3 rows in set (0.07 sec) mysql> create or replace view view_t as select * from t; Query OK, 0 rows affected (0.42 sec) mysql> desc view_t; +----------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------+------+-----+---------+-------+ | quantity | int(11) | YES | | NULL | | | price | int(11) | YES | | NULL | | +----------+---------+------+-----+---------+-------+ 2 rows in set (0.00 sec)
從執行的結果來看。相比原來的檢視view_t,新的檢視view_t少了一個欄位。
4.2、使用alter語句修改檢視
alter語句是MYSQL提供的另外一種修改檢視的方法,語法如下:
alter [algorithm = {undefined | merge | temptable}] view view_name [(column_list)] as select statement [wwith [cascaded | local] check option]
這個語法中的關鍵字和前面檢視的關鍵字是一樣的。
例1:使用alter語句修改檢視view_t,程式碼如下:
alter view view_t as select quantity from t;
執行結果如下:
mysql> desc view_t; +----------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------+------+-----+---------+-------+ | quantity | int(11) | YES | | NULL | | | price | int(11) | YES | | NULL | | +----------+---------+------+-----+---------+-------+ 2 rows in set (0.07 sec) mysql> alter view view_t as select quantity from t; Query OK, 0 rows affected (0.21 sec) mysql> desc view_t; +----------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+---------+------+-----+---------+-------+ | quantity | int(11) | YES | | NULL | | +----------+---------+------+-----+---------+-------+ 1 row in set (0.01 sec)
通過alter語句同樣可以達到修改檢視view_t的目的,從上面的執行過程來看,檢視view_t只剩下1個quantity欄位,修改成功。
5、更新檢視
更新檢視是指通過檢視來插入、更新、刪除表中的資料,因為檢視是一個虛擬表,其中沒有資料。通過檢視更新的時候都是轉到基本表上進行更新的,如果對檢視增加或者刪除記錄,實際上是對其基本表增加或者刪除記錄。
例1:使用update語句更新檢視view_t,程式碼如下:
update view_t set quantity=5;
執行檢視更新之前,檢視基本表和檢視的資訊,執行結果如下:
mysql> select * from view_t; +----------+ | quantity | +----------+ | 3 | +----------+ 1 row in set (0.03 sec) mysql> select * from t; +----------+-------+ | quantity | price | +----------+-------+ | 3 | 50 | +----------+-------+ 1 row in set (0.00 sec) mysql> update view_t set quantity=5; Query OK, 1 row affected (0.14 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t; +----------+-------+ | quantity | price | +----------+-------+ | 5 | 50 | +----------+-------+ 1 row in set (0.00 sec) mysql> select * from view_t; +----------+ | quantity | +----------+ | 5 | +----------+ 1 row in set (0.00 sec) mysql> select * from view_t2; +------+-------+-------+ | qty | price | total | +------+-------+-------+ | 5 | 50 | 250 | +------+-------+-------+ 1 row in set (0.07 sec)
對檢視view_t更新後,基本表t的內容也更新了,同樣當對基本表t更新後,另外一個檢視view_t2中的內容也會更新。
例2:使用insert語句在基本表t中插入一條記錄,程式碼如下:
insert into t values(3,5);
執行結果如下:
mysql> insert into t values(3,5); Query OK, 1 row affected (0.05 sec) mysql> select * from t; +----------+-------+ | quantity | price | +----------+-------+ | 5 | 50 | | 3 | 5 | +----------+-------+ 2 rows in set (0.00 sec) mysql> select * from view_t2; +------+-------+-------+ | qty | price | total | +------+-------+-------+ | 5 | 50 | 250 | | 3 | 5 | 15 | +------+-------+-------+ 2 rows in set (0.00 sec) mysql> select * from view_t; +----------+ | quantity | +----------+ | 5 | | 3 | +----------+ 2 rows in set (0.00 sec)
向表t中插入一條記錄,通過select 查看錶t和檢視view_t2,可以看到其中的內容也隨之更新,檢視更新的不僅僅是數量和單價,總價也會更新。
例3:使用delete語句刪除檢視view_t2中的一條記錄,程式碼如下:
mysql> delete from view_t2 where price=5; Query OK, 1 row affected (0.10 sec) mysql> select * from view_t2; +------+-------+-------+ | qty | price | total | +------+-------+-------+ | 5 | 50 | 250 | +------+-------+-------+ 1 row in set (0.00 sec) mysql> select * from view_t; +----------+ | quantity | +----------+ | 5 | +----------+ 1 row in set (0.00 sec) mysql> select * from t; +----------+-------+ | quantity | price | +----------+-------+ | 5 | 50 | +----------+-------+ 1 row in set (0.00 sec)
在檢視view_t2中刪除price=5的記錄,檢視中的刪除操作最終是通過刪除基本表中相關的記錄實現的,檢視刪除操作之後的表t和檢視view_t2,可以看到通過檢視刪除其所依賴的基本表的資料。
當檢視中包含有如下內容時,檢視的更新操作將不能被執行:
-
檢視中不包含基表中被定義為非空的列。
-
在定義檢視的select語句後的欄位列表中使用了數學表示式。
-
在定義檢視的select語句後的欄位列表中使用了聚合函式。
-
在定義檢視的select語句中使用了distinct,union,top,group by或having子句。
6、刪除檢視
當檢視不再需要時,可以將其刪除,刪除一個或多個檢視可以使用drop view 語句,語法如下:
drop view [if exists] view_name [, view_name] ... [restrict | cascade]
其中,view_name是要刪除的檢視名稱,可以新增多個需要刪除的檢視名稱,各個名稱之間用逗號分隔開。刪除檢視必須擁有drop許可權。
例1:刪除stu_glass檢視,程式碼如下:
drop view if exists stu_glass;
執行結果:
mysql> show create view stu_glass; +-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ | View | Create View | character_set_client | collation_connection | +-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ | stu_glass | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `stu_glass` (`id`,`name`,`glass`) AS select `student`.`s_id` AS `s_id`,`student`.`name` AS `name`,`stu_info`.`glass` AS `glass` from (`student` join `stu_info`) where (`student`.`s_id` = `stu_info`.`s_id`) | gbk | gbk_chinese_ci | +-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+ 1 row in set (0.01 sec) mysql> drop view if exists stu_glass; Query OK, 0 rows affected (0.05 sec) mysql> show create view stu_glass; ERROR 1146 (42S02): Table 'mysql_study.stu_glass' doesn't exist
可以看出,stu_glass檢視已經不存在,刪除成功。
7、答疑解惑
疑問:MySQL中檢視和表的區別以及聯絡是什麼?
1.兩者的區別:
-
檢視是已經編譯好的SQL語句,是基於SQL語句的結果集的視覺化的表,而表不是。
-
檢視沒有實際的物理記錄,而表有。
-
表是內容,檢視是視窗。
-
表佔用物理空間而檢視不佔用物理空間,檢視只是邏輯概念的存在,表可以及時對它進行修改,但檢視只能用建立的語句來修改。. 檢視是檢視資料表的一種方法,可以查詢資料表中某些欄位構成的資料,只是一些SQL語句的集合。 從安全的角度 來說,檢視可以防止使用者接觸資料表,因而使用者不知道表結構。
-
表屬於全域性模式中的表,是實表;檢視屬於區域性模式的表,是虛表。
-
檢視的建立和刪除隻影響檢視本身,不影響對應的基本表。
2.兩者的聯絡:
檢視是在基本表之上建立的表,它的結構(即所定義的列)和內容(即所有記錄)都來自基本表,它依據基本表存在而存在。一個檢視可以對應一個基本表,也可以對應多個基本表。檢視是基本表的抽象和在邏輯意義上建立的新關係。
&n