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