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.兩者的聯系:
視圖是在基本表之上建立的表,它的結構(即所定義的列)和內容(即所有記錄)都來自基本表,它依據基本表存在而存在。一個視圖可以對應一個基本表,也可以對應多個基本表。視圖是基本表的抽象和在邏輯意義上建立的新關系。