MySQL的視圖
MySQL同其它數據庫一樣都有視圖-VIEW,VIEW並不是真實存在的表,它其實是通過SELECT查詢出來的投影(結果)來當成表來查詢,在VIEW中存儲的其實都是事先寫好的SELECT語句,這樣在平時就可以直接查詢VIEW中的內容而查詢到相應數據,在這裏就用簡單的2張表來演示下,建表的SQL如下附件,而在MySQL中創建刪除VIEW也很簡單:
創建: CREATE VIEW 視圖名 AS SELECT語句 修改: ALTER VIEW 視圖名 AS SELECT語句 刪除: DROP VIEW 視圖名
而在MySQL中創建好的視圖是當成MySQL中沒有任何屬性的表存在於數據庫中Comment信息是VIEW的表,可以通過查看表的狀態信息得知,創建好的VIEW物理文件則是在datadir下的數據文件夾中僅有一個MyISAM引擎的表結構文件,類似於MySQL的性能信息庫performance_schema一樣,其實performance_schema就是視圖
mysql> SHOW TABLES; mysql> SHOW TABLE STATUS\G
總的來說VIEW一般用於以下幾個場景中:
1、簡化子查詢
在經常查詢SQL中有子查詢,如:
mysql> use my_test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> SELECT -> * -> FROM -> ( -> SELECT -> * -> FROM -> book_tbl t -> WHERE -> t.storage_date REGEXP ‘^2017.*$‘ -> ) tmp -> WHERE -> tmp.book_name REGEXP ‘^C‘; +---------+-----------+--------------+ | book_id | book_name | storage_date | +---------+-----------+--------------+ | 5 | C | 2017-04-05 | +---------+-----------+--------------+ 1 row in set (0.00 sec)
在這種情況下就可以創建視圖,平時只要直接查詢視圖即可獲取到數據
CREATE VIEW v_book_c_2017 AS SELECT * FROM ( SELECT * FROM book_tbl t WHERE t.storage_date REGEXP ‘^2017.*$‘ ) tmp WHERE tmp.book_name REGEXP ‘^C‘; #建議用客戶端工具中寫SQL創建 mysql> SELECT * FROM v_book_c_2017; +---------+-----------+--------------+ | book_id | book_name | storage_date | +---------+-----------+--------------+ | 5 | C | 2017-04-05 | +---------+-----------+--------------+ 1 row in set (0.01 sec)
2、表的權限控制
如果一張重要的信息表,如用戶表在某一些MySQL用戶下不能讓其看到所有字段信息時也可以使用視圖,當然直接使用GRANTS授權相應字段也可以,但是這樣用戶在DESCRIBE tablename時還是可以看見表結構的,所以使用GRANTS授權相應字段也不是真正不泄露相應表結構信息的,此時就可以創建VIEW後直接把VIEW授權給用戶即可,還是剛才book_tbl表的例子,某個用戶僅能查詢book_tbl前2個字段內的信息表時,創建相應的VIEW時:
mysql> CREATE VIEW v_book_name AS SELECT -> t.book_id, -> t.book_name -> FROM -> book_tbl t; Query OK, 0 rows affected (0.01 sec) mysql> SELECT * FROM v_book_name; +---------+-----------+ | book_id | book_name | +---------+-----------+ | 1 | PHP | | 2 | MySQL | | 3 | Java | | 4 | Python | | 5 | C | | 6 | Shell | +---------+-----------+ 6 rows in set (0.00 sec)
3、大數據表分表
在一張數據量極大的表中平時有大量的查詢部分信息,此時在創建VIEW的時候寫好SELECT的查詢條件後,創建的VIEW就可以當成分表來查詢使用,這樣就可以不加條件SELECT * FROM 視圖名 查詢相應的數據信息,如在book_tbl表中需要查詢2017年入庫的圖書信息,即可以以下方式創建VIEW:
mysql> CREATE VIEW v_book_2017 AS SELECT -> * -> FROM -> book_tbl t -> WHERE -> t.storage_date REGEXP ‘^2017.*$‘; Query OK, 0 rows affected (0.01 sec) mysql> SELECT * FROM v_book_2017; +---------+-----------+--------------+ | book_id | book_name | storage_date | +---------+-----------+--------------+ | 1 | PHP | 2017-04-12 | | 2 | MySQL | 2017-04-12 | | 5 | C | 2017-04-05 | | 6 | Shell | 2017-09-03 | +---------+-----------+--------------+ 4 rows in set (0.00 sec)
4、查詢多張表關聯信息
在平時的時候需要經常查詢多張表的聚合信息時就可以創建好VIEW已簡化平時寫的大量SQL,這樣多張表的聚合或者是關聯信息就可以當成表來查詢,從而可以簡化相應的建立工作,如在book_tbl表和book_price表中找出已經有價格上市的書籍,如下:
mysql> CREATE VIEW v_listed_book AS SELECT -> a.book_id, -> a.book_name, -> b.book_price -> FROM -> book_tbl a -> JOIN book_price b ON a.book_name = b.book_name; Query OK, 0 rows affected (0.01 sec) mysql> SELECT * FROM v_listed_book; +---------+-----------+------------+ | book_id | book_name | book_price | +---------+-----------+------------+ | 1 | PHP | 10.000 | | 2 | MySQL | 22.000 | | 3 | Java | 9.500 | | 6 | Shell | 20.000 | +---------+-----------+------------+ 4 rows in set (0.00 sec)
當然在使用MySQL的VIEW的過程中需要註意的幾點是:一、MySQL自身並不是很擅長子查詢,在MySQL做子查詢查詢時,需要對子查詢啟別名當成臨時表來查詢,在Oracle或者SqlServer中因為有另行封裝開發過是不需要的,這一點比較重要,不然在MySQL的子查詢或報1093錯誤;二、MySQL無法做到真正的物化視圖,當然通過建立真實表利用觸發器也可以實現,但是都不是MySQL自身就有物化視圖,所以MySQL的視圖也僅能用於查詢,且不能寫註釋,而且建議平時不要使用大量的物化視圖,以免導致在創建時不當反而導致性能下降且移植性降低;三、在VIEW中是可以建立視圖的視圖的,即在VIEW的基礎上再建立VIEW,但是建議平時不要這麽使用,以免當前一者VIEW因為刪除導致在關聯VIEW的視圖失效,在日常生產環境中需要避免這樣使用。四、VIEW中存儲的是寫好的SELECT語句,所以在視圖中查出來的數據都是真實表的投影數據,當VIEW關聯的真實表發生改變則VIEW的數據也會改變,且當真實表改名或者刪除時VIEW也會失效,所以在使用視圖VIEW時需要在日常真實表改變時修改或刪除。
本文出自 “Jim的技術隨筆” 博客,謝絕轉載!
MySQL的視圖