參考:《MySQL必知必會》Ben Forta著,第22章 使用視圖
什麼是視圖
視圖是虛擬的表。與包含數據的表不一樣,視圖只包含使用時動態檢索數據的查詢。
例如將三張表聯結查詢數據,可以使用如下查詢語句
mysql> SELECT cust_name,cust_contact FROM customers,orders,orderitems WHERE customers.cust_id = orders.cust_id
-> AND orderitems.order_num = orders.order_num
-> AND prod_id = 'TNT2';
+----------------+--------------+
| cust_name | cust_contact |
+----------------+--------------+
| Coyote Inc. | Y Lee |
| Yosemite Place | Y Sam |
+----------------+--------------+
2 rows in set (0.00 sec)
mysql>
mysql> SHOW TABLES;
+------------------+
| Tables_in_supply |
+------------------+
| customers |
| orderitems |
| orders |
| productnotes |
| products |
| vendors |
+------------------+
6 rows in set (0.00 sec)
mysql> DESC customers;
+--------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------+------+-----+---------+----------------+
| cust_id | int(11) | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| cust_address | char(50) | YES | | NULL | |
| cust_city | char(50) | YES | | NULL | |
| cust_state | char(5) | YES | | NULL | |
| cust_zip | char(10) | YES | | NULL | |
| cust_country | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
| cust_email | char(255) | YES | | NULL | |
+--------------+-----------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
mysql> DESC orders;
+------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+----------+------+-----+---------+----------------+
| order_num | int(11) | NO | PRI | NULL | auto_increment |
| order_date | datetime | NO | | NULL | |
| cust_id | int(11) | NO | MUL | NULL | |
+------------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> DESC orderitems;
+------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+-------+
| order_num | int(11) | NO | PRI | NULL | |
| order_item | int(11) | NO | PRI | NULL | |
| prod_id | char(10) | NO | MUL | NULL | |
| quantity | int(11) | NO | | NULL | |
| item_price | decimal(8,2) | NO | | NULL | |
+------------+--------------+------+-----+---------+-------+
5 rows in set (0.00 sec)
mysql>
可以把整個查詢包裝成一個名爲productcustomers的虛擬表作爲視圖,它不包含表中應該有的任何列或數據,它包含的是一個SQL查詢。
mysql> CREATE VIEW productcustomers AS
-> SELECT cust_name, cust_contact, prod_id FROM customers,orders,orderitems
-> WHERE customers.cust_id=orders.cust_id AND orderitems.order_num=orders.order_num;
Query OK, 0 rows affected (0.03 sec)
mysql>
可以用於檢索。
mysql> SELECT * FROM productcustomers;
+----------------+--------------+---------+
| cust_name | cust_contact | prod_id |
+----------------+--------------+---------+
| Coyote Inc. | Y Lee | ANV01 |
| Coyote Inc. | Y Lee | ANV02 |
| Coyote Inc. | Y Lee | TNT2 |
| Coyote Inc. | Y Lee | FB |
| Coyote Inc. | Y Lee | FB |
| Coyote Inc. | Y Lee | OL1 |
| Coyote Inc. | Y Lee | SLING |
| Coyote Inc. | Y Lee | ANV03 |
| Wascals | Jim Jones | JP2000 |
| Yosemite Place | Y Sam | TNT2 |
| E Fudd | E Fudd | FC |
+----------------+--------------+---------+
11 rows in set (0.00 sec)
mysql>
使用視圖的原因
重用SQL語句。
簡化複雜的SQL操作。在編寫查詢後,可以方便地重用它而不必知道它的基本查詢細節。
使用表的組成部分而不是整個表。
保護數據。可以給用戶授予表的特定部分的訪問權限而不是整個表的訪問權限。
更改數據格式和表示。視圖可返回與底層表的表示和格式不同的數據。
使用視圖
視圖用CREATE VIEW語句來創建。
使用SHOW CREATE VIEW viewname;來查看創建視圖的語句。
用DROP刪除視圖,其語法爲DROP VIEW viewname;。
更新視圖時,可以先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。
(1)用視圖簡化複雜的聯結,上述例子
mysql> SELECT cust_name, cust_contact FROM productcustomers WHERE prod_id = 'TNT2';
+----------------+--------------+
| cust_name | cust_contact |
+----------------+--------------+
| Coyote Inc. | Y Lee |
| Yosemite Place | Y Sam |
+----------------+--------------+
2 rows in set (0.00 sec)
mysql>
(2)用視圖重新格式化檢索出的,組合供應商名和位置
mysql> DESC vendors;
+--------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+----------------+
| vend_id | int(11) | NO | PRI | NULL | auto_increment |
| vend_name | char(50) | NO | | NULL | |
| vend_address | char(50) | YES | | NULL | |
| vend_city | char(50) | YES | | NULL | |
| vend_state | char(5) | YES | | NULL | |
| vend_zip | char(10) | YES | | NULL | |
| vend_country | char(50) | YES | | NULL | |
+--------------+----------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
mysql> SELECT * FROM vendors LIMIT 1;
+---------+-------------+-----------------+------------+------------+----------+--------------+
| vend_id | vend_name | vend_address | vend_city | vend_state | vend_zip | vend_country |
+---------+-------------+-----------------+------------+------------+----------+--------------+
| 1001 | Anvils R Us | 123 Main Street | Southfield | MI | 48075 | USA |
+---------+-------------+-----------------+------------+------------+----------+--------------+
1 row in set (0.00 sec)
mysql> SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
+------------------------+
| vend_title |
+------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+------------------------+
6 rows in set (0.00 sec)
mysql> CREATE VIEW vendorlocations AS
-> SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT * FROM vendorlocations;
+------------------------+
| vend_title |
+------------------------+
| ACME(USA) |
| Anvils R Us(USA) |
| Furball Inc.(USA) |
| Jet Set(England) |
| Jouets Et Ours(France) |
| LT Supplies(USA) |
+------------------------+
6 rows in set (0.00 sec)
mysql>
(3)用視圖過濾不想要的數據,過濾沒有電子郵件地址的客戶
mysql> SHOW customers;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'customers' at line 1
mysql>
mysql>
mysql> DESC customers;
+--------------+-----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-----------+------+-----+---------+----------------+
| cust_id | int(11) | NO | PRI | NULL | auto_increment |
| cust_name | char(50) | NO | | NULL | |
| cust_address | char(50) | YES | | NULL | |
| cust_city | char(50) | YES | | NULL | |
| cust_state | char(5) | YES | | NULL | |
| cust_zip | char(10) | YES | | NULL | |
| cust_country | char(50) | YES | | NULL | |
| cust_contact | char(50) | YES | | NULL | |
| cust_email | char(255) | YES | | NULL | |
+--------------+-----------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
mysql> CREATE VIEW customeremaillist AS
-> SELECT cust_id, cust_name, cust_email FROM customers
-> WHERE cust_email IS NOT NULL;
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT * from customeremaillist;
+---------+----------------+---------------------+
| cust_id | cust_name | cust_email |
+---------+----------------+---------------------+
| 10001 | Coyote Inc. | [email protected] |
| 10003 | Wascals | [email protected] |
| 10004 | Yosemite Place | [email protected] |
+---------+----------------+---------------------+
3 rows in set (0.00 sec)
mysql>
(4)使用視圖與計算字段,計算物品總價
mysql> SELECT * FROM orderitems LIMIT 1;
+-----------+------------+---------+----------+------------+
| order_num | order_item | prod_id | quantity | item_price |
+-----------+------------+---------+----------+------------+
| 20005 | 1 | ANV01 | 10 | 5.99 |
+-----------+------------+---------+----------+------------+
1 row in set (0.00 sec)
mysql> CREATE VIEW orderitemsexpanded AS
-> SELECT order_num, prod_id, quantity, item_price, quantity*item_price AS expanded_price FROM orderitems;
Query OK, 0 rows affected (0.03 sec)
mysql> SELECT * FROM orderitemsexpanded WHERE order_num = 20005;
+-----------+---------+----------+------------+----------------+
| order_num | prod_id | quantity | item_price | expanded_price |
+-----------+---------+----------+------------+----------------+
| 20005 | ANV01 | 10 | 5.99 | 59.90 |
| 20005 | ANV02 | 3 | 9.99 | 29.97 |
| 20005 | TNT2 | 5 | 10.00 | 50.00 |
| 20005 | FB | 1 | 10.00 | 10.00 |
+-----------+---------+----------+------------+----------------+
4 rows in set (0.00 sec)
mysql>