视图
# 140.视图
视图(View),可以理解为是一个常用的SQL
# 视图是什么
我们可以将频繁使用的select语句(例如月度统计、年度统计),保存为视图,这样就不用每次都重新书写并运行了。
特别是在进行汇总以及复杂的查询条件导致 SELECT 语句非常庞大时,使用视图可以大大提高效率。
# 创建视图
创建视图需要使用 CREATE VIEW 语句 ,语法:
CREATE VIEW 视图名称(<视图列名1>, <视图列名2>, ……)
AS
<SELECT语句>
2
3
SELECT 语句需要书写在 AS 关键字之后。视图中列的排列顺序,和SELECT 语句中列的排列顺序相同。视图的列名在视图名称之后的列表中定义。
举例:我们将商品类型和数量做一个视图
create view ProductSum (product_type, cnt_product)
as
select product_type, count(*)
from Product
group by product_type;
2
3
4
5
# 从视图中查询数据
然后我们就可以使用视图了,我们可以将视图当成一个表:
select product_type, cnt_product
from ProductSum;
--结果:
+--------------+-------------+
| product_type | cnt_product |
+--------------+-------------+
| 衣服 | 2 |
| 办公用品 | 2 |
| 厨房用具 | 4 |
+--------------+-------------+
3 rows in set (0.00 sec)
2
3
4
5
6
7
8
9
10
11
12
13
视图和表的不同在于,视图并不会保存实际的数据。
我们在创建表时,会通过 INSERT 语句将数据保存到数据库之中,而数据库会将数据保存到磁盘上。在使用 SELECT 语句查询数据时,实际上就是从磁盘中读取数据,进行各种计算之后,再将结果返回给用户。
但是使用视图时并不会将数据保存到存储设备之中,而且也不会将数据保存到其他任何地方 。实际上视图保存的是 SELECT 语句。
创建出视图之后,就可以通过非常简单的 SELECT 语句,随时得到想要的汇总结果。并且由于视图不保存数据,当Product 表中的数据更新之后,视图也会自动更新,非常灵活方便。
# 修改视图
# 多重视图
多重视图:以视图为基础创建的视图
举例:
create view ProductSumJim(product_type, cnt_product)
as
select product_type, cnt_product
from ProductSum
where product_type='办公用品';
2
3
4
5
使用视图:
-- 确认创建好的视图
SELECT product_type, cnt_product
FROM ProductSumJim;
--结果:
+--------------+-------------+
| product_type | cnt_product |
+--------------+-------------+
| 办公用品 | 2 |
+--------------+-------------+
1 row in set (0.00 sec)
2
3
4
5
6
7
8
9
10
11
# 视图的缺点
从视图中查询数据时,通常有如下两个步骤:
- 首先执行定义视图的 SELECT 语句
- 根据得到的结果,再执行在从视图查询数据的SQL
也就是说,使用视图的查询通常需要执行 2 条以上的 SELECT 语句(不同DBMS内部实现不同)。如果是多重视图,还会进一步降低SQL的性能。因此,应该避免在视图的基础上创建视图。
# 视图的限制
虽然之前我们说过在定义视图时可以使用任何 SELECT 语句,但ORDER BY 子句除外。为什么?这是因为视图和表一样,数据行都是没有顺序的。
有些 DBMS 在定义视图的语句中是可以使用 ORDER BY 子句的 (例如PostgreSQL),但这并不是通用的语法。因此,在定义视图时请不要使用 ORDER BY 子句。
此外,视图是无法随意更新的。虽然视图和表很像,几乎可以使用任何select语句;但本质上视图只是一个SQL,归根结底,视图的数据是从表中获取的,如果原表可以更新,那么视图中的数据也可以更新。反之亦然,如果视图发生了改变,而原表没有进行相应更新的话,就无法保证数据的一致性了。
就比如我们向视图 ProductSum 中添加数据 (' 电器制品 ',5) 时,原表 Product 应该如何更新才好呢?按理说应该向表中添加商品种类为“电器制品”的 5 行数据,但是这些商品对应的商品编号、商品名称和销售单价等我们都不清楚。数据库在这里就遇到了麻烦。
在某些特定条件下,视图也可以更新的,这里不推荐这么做,因此不展开。
# 删除视图
删除视图需要使用 DROP VIEW 语句:
DROP VIEW 视图名称;
注意多重视图的问题。如果视图B,是从视图A的基础上创建出来的,那么删除视图A就会出错。
如果要将B也删除,得使用级联关键字CASCADE:
DROP VIEW A CASCADE;
# 查看视图的结构
如何查看一个视图的结构呢(类似表结构)?也可以使用DESCRIBE(或简写为DESC):
DESCRIBE ProductSum;
--结果:
+--------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| product_type | varchar(32) | NO | | NULL | |
| cnt_product | bigint | NO | | 0 | |
+--------------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
2
3
4
5
6
7
8
9
10
那查看视图的SQL呢?使用SHOW CREATE VIEW <视图名>;
但是在命令行里查看的话很不美观,看起来不方便,可以用Navicat等工具查看
(完)