ps:视图是MySQL 5以及后面的版本加进去的。所以本节内容适用于MySQl 5及往后的版本。

为了更好的理解视图,让我们先看一个栗子:
用 SELECT 语句从一个表中检索一些数据。

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';

这里用了表联结来检索特定产品的客户,包括客户的姓名和联系方式。由于用了表联结,语句很长,不仅读起来比较麻烦,而且当你在不同的地方都要用到这些内容的时候,你重新写这么一段长代码?
现在,假如可以把整个查询包装成一个名为 productcustomers 的虚拟表,我们就可以轻松的检索出相同的数据:

SELECT cust_name,cust_contact 
FROM productcustomers 
WHERE prod_id = 'TNT2';

这就是视图的作用,productcustomers 虚拟表其实就是一个视图,作为视图,它并不包含表中应该有的任何列或数据,它包含的仅仅是一个SQL查询(与上面用以正确联结表的相同的查询)。

如上面所说,我们应该认识到,视图仅仅是用来查看存储在别处的数据的一种设施。视图本身不包含数据(表中应有的列或数据)!因此视图返回的数据是从其他表中检索出来的,在添加或更改这些表中的数据时,视图将返回改变过的数据。

一、使用视图:

1、视图用CREATE VIEW + 视图名(与表名一样,唯一);
2、创建完视图,可以用SHOW CREATE VIEW + 视图名 来查看创建视图的语句。

利用视图简化复杂的联结:
视图最常见的作用之一是隐藏复杂的SQL,而复杂的SQL通常涉及到表联结。栗子:

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;

这条语句创建了一个名为 productcustomers 的视图,它联结了三个表,以返回已经订购了任意产品的所有客户的列表,现在我们用MYSQL客户机可以看到,我们已经创建了一个视图(我用的是Navicat for mysql):

mysql 视图的使用优缺点 mysql的视图怎么理解_SQL

点开它(话说那个眼镜好帅)

mysql 视图的使用优缺点 mysql的视图怎么理解_SQL_02

我们可以看到,我们要的数据都跟我们想要的方式列(检索)出来了。
当然,由于视图也可以理解成一张虚拟的表,因此我们可以用查看表的形式查看视图:

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

检索购买特定产品的客户列表:

SELECT * FROM productcustomers WHERE prod_id = 'TNT2';

//返回
+----------------+--------------+---------+
| cust_name      | cust_contact | prod_id |
+----------------+--------------+---------+
| Coyote Inc.    | Y Lee        | TNT2    |
| Yosemite Place | Y Sam        | TNT2    |
+----------------+--------------+---------+

当我们要在很多地方都要获取到这些数据的时候,视图就显得很方便了,它极大的简化了复杂SQL语句的使用。

用视图重新格式化检索出来的数据:
在这里我们实现两个列的数据的拼接(格式:供应商(国家)):

SELECT Concat(vend_name,'(',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)       |
+------------------------+

假如我们经常需要用到这个格式,为了不用每次都用到拼接函数Concat(),我们可以创建一个视图:

CREATE VIEW vendorlocation AS 
SELECT Concat(vend_name,'(',vend_country,')')
AS vend_title FROM vendors 
ORDER BY vend_name;

//我们检索一下这个视图
SELECT * FROM vendorlocation;

//返回
+------------------------+
| vend_title             |
+------------------------+
| ACME(USA)              |
| Anvils R Us(USA)       |
| Furball Inc.(USA)      |
| Jet Set(England)       |
| Jouets Et Ours(France) |
| LT Supplies(USA)       |
+------------------------+
//跟之前的一样吧。。。

用视图过滤不想要的数据:
视图对于应用普通的WHERE子句也是很有用的,例如,我们可以定义customeremaillist视图,它过滤没有电子邮件的客户:

CREATE VIEW customeremaillist AS 
SELECT cust_id,cust_name,cust_email 
FROM customers WHERE cust_email IS NOT NULL;

//这样我们就可以获得由电子邮件的用户,我们还可以获取特定电子邮件的客户
SELECT * FROM customeremaillist 
WHERE cust_email = 'sam@yosemite.com';

//返回
+---------+----------------+------------------+
| cust_id | cust_name      | cust_email       |
+---------+----------------+------------------+
|   10004 | Yosemite Place | sam@yosemite.com |
+---------+----------------+------------------+

如果在视图检索数据时使用了一条WHERE子句,后面从索引中检索数据又用了一条WHERE,则这两条WHERE子句将会自动组合。

使用视图与计算字段:
现在我们检索订单详情表中某个特定订单的物品,计算每种物品的总价格

SELECT prod_id,quantity,item_price,quantity*item_price 
AS total_price FROM orderitems WHERE order_num = 20005;

//返回
+---------+----------+------------+-------------+
| prod_id | quantity | item_price | total_price |
+---------+----------+------------+-------------+
| ANV01   |       10 | 5.99       | 59.90       |
| ANV02   |        3 | 9.99       | 29.97       |
| TNT2    |        5 | 10         | 50.00       |
| FB      |        1 | 10         | 10.00       |
+---------+----------+------------+-------------+

//用视图实现:
CREATE VIEW view_order_items AS 
SELECT prod_id,quantity,item_price,quantity*item_price 
AS total_price FROM orderitems;

//检索订单20005的详细内容:
SELECT * FROM view_order_item WHERE order_num = 20005;

//返回同样结果

在上面的例子中,我们创建了4个视图:

mysql 视图的使用优缺点 mysql的视图怎么理解_SQL_03

那么,我们怎样删除或者更改这些视图呢?

二、删除或更改视图:

1、删除:
由于前面说到,视图就类似与一张虚拟的表,因此视图的删除也类似于表的删除:

DROP VIEW +视图名
//删除表:DROP TABLE +表名

2、修改:
可以先用 DROP 删除,再用 CREATE 创建,也可以直接用CREATE OR REPLACE VIEW ,如果要更新的视图不存在,则CREATE OR REPLACE VIEW 会创建一个视图,如果存在,则替换现有视图。
类似于数据表,我们同样可以用 ALTER 来更改视图。

视图为虚拟的表,它们包含的不是数据而是根据需要检索数据的查询,视图提供了一种MYSQL的SELECT语句层次的封装,可用来简化数据处理以及重新格式化基础数据或保护基础数据。

但是!因为视图不包含数据,所以每次使用视图时,都必须处理查询执行时所需的任一检索,如果你用多个联结和过滤创建了复杂的视图或者嵌套了视图,可能会使性能下降的厉害。因此,在使用大量视图前,应该进行简单的测试。

本博客参考自《mysql必知必会》