天天看點

深入解析MySQL:視圖

作者:JAVA後端架構
深入解析MySQL:視圖

概述

很多時候,我們會有一些很複雜的資料庫操作,比如整合使用者的行為資料,那這些資料可能包含使用者的餐飲、生活日用、充值消費、交通出行、通訊物流、交通出行、醫療保健、住房物業、運動健康...

基于此,我們可能要去關聯很多的使用者行為資訊表,寫一大堆的合并、統計,以及條件過濾的腳本,來輸出最終的二維表,這才是使用者真正需要的資料。如果把這些複雜的腳本寫在業務程式中不是很合理,那有什麼辦法把

這些腳本細節隐藏,隻顯示隻顯示簡潔的結果呢,那就要用到視圖了。

視圖是由資料庫中的一個表或多個表導出的虛拟表,是一種虛拟存在的表,友善使用者對資料的操作。

概念

視圖是在mysql5之後出現的,是一種虛拟表,行和列的資料來自于定義視圖時使用的一些表中,視圖的資料是在使用視圖的時候動态生成的,視圖隻儲存了sql的邏輯,不儲存查詢的結果。

使用場景

多個業務場景使用到相同的查詢結果,并且該查詢結果比較複雜的時候,我們可以使用視圖來隐藏複雜的實作細節。

視圖和表比較

深入解析MySQL:視圖

視圖的作用

對其中所引用的基礎表來說,視圖的作用類似于篩選。定義視圖的篩選可以來自目前或其他資料庫的一個或多個表,或者其他視圖。通過視圖進行查詢沒有任何限制,通過它們進行資料修改時的限制也很少。視圖的作用歸納為如下幾點。

1、簡單性

看到的就是需要的。視圖不僅可以簡化使用者對資料的了解,也可以簡化他們的操作。那些被經常使用的查詢可以被定義為視圖,進而使得使用者不必為以後的操作每次指定查詢的條件。

經常需要聯合查詢的内容也可以指定為視圖,這樣就不需要每次都寫大量的聯表腳本。

2、安全性

視圖的安全性可以防止未授權使用者檢視特定的行或列,使有權限使用者隻能看到表中特定行的方法,比如把隻有某部分資料查詢視圖授權給某個使用者。

3、邏輯資料獨立性

視圖可以使應用程式和資料庫表在一定程度上獨立。如果沒有視圖,程式一定是建立在表上的。有了視圖之後,程式可以建立在視圖之上,進而程式與資料庫表被視圖分割開來。視圖可以在以下幾個方面使程式與資料獨立。

(1)如果應用建立在資料庫表上,當資料庫表發生變化時,可以在表上建立視圖,通過視圖屏蔽表的變化,進而使應用程式可以不動。

(2)如果應用建立在資料庫表上,當應用發生變化時,可以在表上建立視圖,通過視圖屏蔽應用的變化,進而使資料庫表不動。

(3)如果應用建立在視圖上,當資料庫表發生變化時,可以在表上修改視圖,通過視圖屏蔽表的變化,進而使應用程式可以不動。

(4)如果應用建立在視圖上,當應用發生變化時,可以在表上修改視圖,通過視圖屏蔽應用的變化,進而使資料庫可以不動。

資料準備

深入解析MySQL:視圖

建立視圖

MySQL中,建立視圖是通過CREATE VIEW語句實作的。

文法

1 CREATE [OR REPLACE] [ALGORITHM={UNDEFINED|MERGE|TEMPTABLE}]
2 VIEW ViewName[(ColumnList)]
3 AS SELECT ...
4 [WITH [CASCADED|LOCAL] CHECK OPTION];           

參數說明:

(1)ALGORITHM:可選項,表示視圖選擇的算法。

(2)ViewName 視圖名:表示要建立的視圖名稱。

(3)ColumnList 屬性清單:可選項,指定視圖中各個屬性的名詞,預設情況下與SELECT語句中的查詢的屬性相同。

(4)SELECT語句:表示一個完整的查詢語句,将查詢記錄導入視圖中。

(5)WITH CHECK OPTION:可選項,表示更新視圖時要保證在該視圖的權限範圍之内。

視圖的使用步驟

(1)建立視圖

(2)對視圖執行查詢操作

對單表的操作

查詢出訂單表中,單筆訂單額度超過100元的資料,下面依次展示建立視圖和查詢視圖。

1 mysql> select *  from t_order;
 2 +---------+-----+-------+--------+---------------------+------+
 3 | orderid | uid | uname | amount | time                | year |
 4 +---------+-----+-------+--------+---------------------+------+
 5 |      20 |   1 | brand | 91.23  | 2018-08-20 17:22:21 | 2018 |
 6 |      21 |   1 | brand | 87.54  | 2019-07-16 09:21:30 | 2019 |
 7 |      22 |   1 | brand | 166.88 | 2019-04-04 12:23:55 | 2019 |
 8 |      23 |   2 | helyn | 93.73  | 2019-09-15 10:11:11 | 2019 |
 9 |      24 |   2 | helyn | 102.32 | 2019-01-08 17:33:25 | 2019 |
10 |      25 |   2 | helyn | 106.06 | 2019-12-24 12:25:25 | 2019 |
11 |      26 |   2 | helyn | 73.42  | 2020-04-03 17:16:23 | 2020 |
12 |      27 |   3 | sol   | 55.55  | 2019-08-05 19:16:23 | 2019 |
13 |      28 |   3 | sol   | 69.96  | 2020-09-16 19:23:16 | 2020 |
14 |      29 |   4 | weng  | 199.99 | 2020-06-08 19:55:06 | 2020 |
15 +---------+-----+-------+--------+---------------------+------+
16 10 rows in set
17 
18 mysql> create view view1
19     -> as select * from t_order where amount >100;
20 Query OK, 0 rows affected
21 
22 mysql> select * from view1;
23 +---------+-----+-------+--------+---------------------+------+
24 | orderid | uid | uname | amount | time                | year |
25 +---------+-----+-------+--------+---------------------+------+
26 |      22 |   1 | brand | 166.88 | 2019-04-04 12:23:55 | 2019 |
27 |      24 |   2 | helyn | 102.32 | 2019-01-08 17:33:25 | 2019 |
28 |      25 |   2 | helyn | 106.06 | 2019-12-24 12:25:25 | 2019 |
29 |      29 |   4 | weng  | 199.99 | 2020-06-08 19:55:06 | 2020 |
30 +---------+-----+-------+--------+---------------------+------+
31 4 rows in set
32 
33 mysql>  select * from view1 where year = 2019;
34 +---------+-----+-------+--------+---------------------+------+
35 | orderid | uid | uname | amount | time                | year |
36 +---------+-----+-------+--------+---------------------+------+
37 |      22 |   1 | brand | 166.88 | 2019-04-04 12:23:55 | 2019 |
38 |      24 |   2 | helyn | 102.32 | 2019-01-08 17:33:25 | 2019 |
39 |      25 |   2 | helyn | 106.06 | 2019-12-24 12:25:25 | 2019 |
40 +---------+-----+-------+--------+---------------------+------+
41 3 rows in set           

上面我們建立了一個視圖:view1,我們需要看某個條件下的資訊時,不用關心這個視圖内部是什麼樣的,隻需要查詢視圖就可以了,sql簡單很多。

對多表的操作

有兩個表:學生、班級,資料基數如下,需要建立一個視圖,統計每個班級的人數和平均成績和總成績。

1 mysql> select * from classes;
 2 +---------+-----------+
 3 | classid | classname |
 4 +---------+-----------+
 5 |       1 | 初三一班  |
 6 |       2 | 初三二班  |
 7 |       3 | 初三三班  |
 8 +---------+-----------+
 9 3 rows in set
10 
11 mysql> select * from students;
12 +-----------+-------------+-------+---------+
13 | studentid | studentname | score | classid |
14 +-----------+-------------+-------+---------+
15 |         1 | brand       | 97.5  |       1 |
16 |         2 | helen       | 96.5  |       1 |
17 |         3 | lyn         | 96    |       1 |
18 |         4 | sol         | 97    |       1 |
19 |         7 | b1          | 81    |       2 |
20 |         8 | b2          | 82    |       2 |
21 |        13 | c1          | 71    |       3 |
22 |        14 | c2          | 72.5  |       3 |
23 |        19 | lala        | 51    |       0 |
24 +-----------+-------------+-------+---------+
25 9 rows in set            
1 mysql> create view view2 as select a.classname as '班級名稱',count(b.studentid) as '總人數',sum(b.score) as '總分',avg(b.score) as '平均分'
 2 from classes a inner join students b on a.classid = b.classid 
 3 group by a.classid,a.classname;
 4 Query OK, 0 rows affected
 5 
 6 mysql> select * from view2;
 7 +----------+--------+--------+-----------+
 8 | 班級名稱 | 總人數 | 總分   | 平均分    |
 9 +----------+--------+--------+-----------+
10 | 初三一班 |      4 | 387.00 | 96.750000 |
11 | 初三二班 |      2 | 163.00 | 81.500000 |
12 | 初三三班 |      2 | 143.50 | 71.750000 |
13 +----------+--------+--------+-----------+
14 3 rows in set           

查詢視圖結構

使用 desc viewname 文法檢視視圖的結構

1 mysql> desc view2;
 2 +----------+---------------+------+-----+---------+-------+
 3 | Field    | Type          | Null | Key | Default | Extra |
 4 +----------+---------------+------+-----+---------+-------+
 5 | 班級名稱 | varchar(30)   | YES  |     | NULL    |       |
 6 | 總人數   | bigint(21)    | NO   |     | 0       |       |
 7 | 總分     | decimal(32,2) | YES  |     | NULL    |       |
 8 | 平均分   | decimal(14,6) | YES  |     | NULL    |       |
 9 +----------+---------------+------+-----+---------+-------+
10 4 rows in set           

使用show create view文法檢視視圖建立資訊

1 mysql> show create view view2;
2 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
3 | View  | Create View                                                                                                                                                                                                                                                                                                                                    | character_set_client | collation_connection |
4 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
5 | view2 | CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `a`.`classname` AS `班級名稱`,count(`b`.`studentid`) AS `總人數`,sum(`b`.`score`) AS `總分`,avg(`b`.`score`) AS `平均分` from (`classes` `a` join `students` `b` on((`a`.`classid` = `b`.`classid`))) group by `a`.`classid`,`a`.`classname` | utf8                 | utf8_general_ci      |
6 +-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------+----------------------+
7 1 row in set           

修改視圖

修改視圖是指修改資料庫中已存在的表的定義。當基本表的某些字段發生改變時,可以通過修改視圖來保持視圖和基本表之間一緻。MySQL中通過CREATE OR REPLACE VIEW語句和ALTER VIEW語句來修改視圖。

create or replace方式

當視圖存在時,修改,不存在時,建立新的視圖。

1 mysql> create or replace view view2 as select a.classname as '班級名稱',count(b.studentid) as '總人數',sum(b.score) as '總分',avg(b.score) as '平均分'
 2 from classes a inner join students b on a.classid = b.classid 
 3 group by a.classid,a.classname;
 4 Query OK, 0 rows affected
 5 
 6 mysql> select * from view2;
 7 +----------+--------+--------+-----------+
 8 | 班級名稱 | 總人數 | 總分   | 平均分    |
 9 +----------+--------+--------+-----------+
10 | 初三一班 |      4 | 387.00 | 96.750000 |
11 | 初三二班 |      2 | 163.00 | 81.500000 |
12 | 初三三班 |      2 | 143.50 | 71.750000 |
13 +----------+--------+--------+-----------+
14 3 rows in set            

alter方式

1 mysql> alter view view2 as select a.classname as '班級名稱',count(b.studentid) as '總人數',sum(b.score) as '總分',avg(b.score) as '平均分'
 2 from classes a inner join students b on a.classid = b.classid 
 3 group by a.classid,a.classname;
 4 Query OK, 0 rows affected
 5 
 6 mysql> select * from view2;
 7 +----------+--------+--------+-----------+
 8 | 班級名稱 | 總人數 | 總分   | 平均分    |
 9 +----------+--------+--------+-----------+
10 | 初三一班 |      4 | 387.00 | 96.750000 |
11 | 初三二班 |      2 | 163.00 | 81.500000 |
12 | 初三三班 |      2 | 143.50 | 71.750000 |
13 +----------+--------+--------+-----------+
14 3 rows in set            

删除視圖

删除視圖是指删除資料庫中已存在的視圖。删除視圖時,隻能删除視圖的定義,不會删除資料。MySQL中,使用DROP VIEW語句來删除視圖。但是,使用者必須擁有DROP權限。

文法

1 DROP VIEW IF EXISTS vname1[,vname2][,vname3];           

可以删除多個視圖,多個視圖名稱使用都好隔開。

1 mysql> DROP VIEW IF EXISTS view1,view2;
2 Query OK, 0 rows affected            

更新視圖資料

即更改視圖中的資料,而不是更改視圖中的sql邏輯。當對視圖進行更新後,也會對原始表的資料進行更新。

為了防止對原始表的資料産生更新,可以為視圖添加隻讀權限,隻允許讀視圖,不允許對視圖進行更新。一般比較少這麼操作:

1 mysql> create view view1 as select * from classes;
 2 Query OK, 0 rows affected
 3 
 4 mysql> select * from view1;
 5 +---------+-----------+
 6 | classid | classname |
 7 +---------+-----------+
 8 |       1 | 初三一班  |
 9 |       2 | 初三二班  |
10 |       3 | 初三三班  |
11 +---------+-----------+
12 3 rows in set
13 
14 mysql> insert into view1 values(4,'出三四班');
15 Query OK, 1 row affected
16 
17 mysql> update view1 set classname='初三四班' where classid=4;
18 Query OK, 1 row affected
19 Rows matched: 1  Changed: 1  Warnings: 0
20 
21 mysql> select * from view1;
22 +---------+-----------+
23 | classid | classname |
24 +---------+-----------+
25 |       1 | 初三一班  |
26 |       2 | 初三二班  |
27 |       3 | 初三三班  |
28 |       4 | 初三四班  |
29 +---------+-----------+
30 4 rows in set            

視圖的更新我們一般不使用,為了保護視圖的某部分區間的資料不被修改,一般會使用WITH CHECK OPTION限制 ,甚至設定為隻讀視圖。

with check option

視圖隻操作它能夠查詢出來的資料,對于查詢不出的資料,即使基表中存在資料,也不可以通過視圖來操作。針對這方面的限制有 with check option 表達式進行操作。他對delete、insert、update分别有如下限制:

深入解析MySQL:視圖

下面建立兩個同樣結果的視圖,一個帶with check option,一個不帶。

1 mysql> create view v as select * from  t_order where amount>0;
 2 Query OK, 0 rows affected
 3  
 4 mysql> create view v_option as select * from  t_order where amount>0 with check option;
 5 Query OK, 0 rows affected
 6 
 7 mysql> select * from t_order;
 8 +---------+---------+---------+-------+
 9 | orderid | account | amount  | goods |
10 +---------+---------+---------+-------+
11 |       8 | brand   | 52.2    |     2 |
12 |       9 | hen     | 1752.02 |     7 |
13 |      10 | helyn   | 88.5    |     4 |
14 |      11 | sol     | 1007.9  |    11 |
15 |      12 | diny    | 12      |     1 |
16 |      13 | weng    | 52.2    |     5 |
17 |      14 | sally   | 99.71   |     9 |
18 |      15 | brand1  | -99.99  |     6 |
19 +---------+---------+---------+-------+
20 8 rows in set           

原表有8條資料,因為條件限制,視圖無法讀取到最後一條資料,即隻有前7條資料。那根據上面的規則,使用v_option視圖進行修改,修改他查詢範圍之外的資料應該是不允許的,我們來試試:

1 mysql> update v_option set amount=-8 where orderid=12;
2 1369 - CHECK OPTION failed 'test.v_option'            

amout = -8,改完後資料會跑到視圖可查詢範圍之外,是以被限制了。使用不限制的視圖就可以了,如下:

1 mysql> update v set amount=-8 where orderid=12;
 2 Query OK, 1 row affected
 3 Rows matched: 1  Changed: 1  Warnings: 0
 4 
 5 mysql> select * from t_order;
 6 +---------+---------+---------+-------+
 7 | orderid | account | amount  | goods |
 8 +---------+---------+---------+-------+
 9 |       8 | brand   | 52.2    |     2 |
10 |       9 | hen     | 1752.02 |     7 |
11 |      10 | helyn   | 88.5    |     4 |
12 |      11 | sol     | 1007.9  |    11 |
13 |      12 | diny    | -8      |     1 |
14 |      13 | weng    | 52.2    |     5 |
15 |      14 | sally   | 99.71   |     9 |
16 |      15 | brand1  | -99.99  |     6 |
17 +---------+---------+---------+-------+
18 8 rows in set            

同理,delete、insert 也可以驗證下。

總結

  1. 了解視圖的用途及與表的差別。
  2. 掌握視圖的建立、使用、修改、删除。
  3. 了解視圖的優點:簡單簡潔(隐藏細節,輸出結果)、安全性(使用者隻能看到表中特定行的方法)、邏輯資料獨立性。

為幫助開發者們提升面試技能、有機會入職BATJ等大廠公司,特别制作了這個專輯——這一次整體放出。

大緻内容包括了: Java 集合、JVM、多線程、并發程式設計、設計模式、Spring全家桶、Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、MongoDB、Redis、MySQL、RabbitMQ、Kafka、Linux、Netty、Tomcat等大廠面試題等、等技術棧!

深入解析MySQL:視圖

歡迎大家關注公衆号【Java爛豬皮】,回複【666】,擷取以上最新Java後端架構VIP學習資料以及視訊學習教程,然後一起學習,一文在手,面試我有。

每一個專欄都是大家非常關心,和非常有價值的話題,如果我的文章對你有所幫助,還請幫忙點贊、好評、轉發一下,你的支援會激勵我輸出更高品質的文章,非常感謝!

深入解析MySQL:視圖

繼續閱讀