MySQL 筆記6 視圖

參考:《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>


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章