SQL视图简介
⽬录
学习重点
从 SQL 的⾓度来看,视图和表是相同的,两者的区别在于表中保存的是实际的数据,⽽视图中保存的是SELECT语句(视图本⾝并不存储数据)。
使⽤视图,可以轻松完成跨多表查询数据等复杂操作。
可以将常⽤的SELECT语句做成视图来使⽤。
创建视图需要使⽤CREATE VIEW语句。
视图包含“不能使⽤ORDER BY ”和“可对其进⾏有限制的更新”两项限制。
删除视图需要使⽤DROP VIEW语句。
⼀、视图和表
我们⾸先要学习的是⼀个新的⼯具——视图。
KEYWORD
视图
视图究竟是什么呢?如果⽤⼀句话概述的话,就是“从 SQL 的⾓度来看视图就是⼀张表”。实际上,在 SQL 语句中并不需要区分哪些是表,哪些是视图,只需要知道在更新时它们之间存在⼀些不同就可以了,这⼀点之后会为⼤家进⾏介绍。⾄少在编写SELECT语句时并不需要特别在意表和视图有什么不同。
那么视图和表到底有什么不同呢?区别只有⼀个,那就是“是否保存了实际的数据”。
通常,我们在创建表时,会通过INSERT语句将数据保存到数据库之中,⽽数据库中的数据实际上会被保存到计算机的存储设备(通常是硬盘)中。因此,我们通过SELECT语句查询数据时,实际上就是从存储设备(硬盘)中读取数据,进⾏各种计算之后,再将结果返回给⽤户这样⼀个过程。
但是使⽤视图时并不会将数据保存到存储设备之中,⽽且也不会将数据保存到其他任何地⽅。实际上视图保存的是SELECT语句(图 1)。我们从视图中读取数据时,视图会在内部执⾏该SELECT语句并创建出⼀张临时表。
图 1 视图和表
视图的优点
视图的优点⼤体有两点。第⼀点是由于视图⽆需保存数据,因此可以节省存储设备的容量。例如,我们在中创建了⽤来汇总商品种类(product_type)的表。由于该表中的数据最终都会保存到存储设备之中,因此会占⽤存储设备的数据空间。但是,如果把同样的数据作为视图保存起来的话,就只需要代码清单 1 那样的SELECT语句就可以了,这样就节省了存储设备的数据空间。
代码清单 1 通过视图等SELECT语句保存数据
SELECT product_type, SUM(sale_price), SUM(purchase_price)
FROM Product
GROUP BY product_type;
由于本⽰例中表的数据量充其量只有⼏⾏,所以使⽤视图并不会⼤幅缩⼩数据的⼤⼩。但是在实际的业务中数据量往往⾮常⼤,这时使⽤视图所节省的容量就会⾮常可观了。
法则 1
表中存储的是实际数据,⽽视图中保存的是从表中取出数据所使⽤的SELECT语句。
第⼆个优点就是可以将频繁使⽤的SELECT语句保存成视图,这样就不⽤每次都重新书写了。创建好视图之后,只需在SELECT语句中进⾏调⽤,就可以⽅便地得到想要的结果了。特别是在进⾏汇总以及复杂的查询条件导致SELECT语句⾮常庞⼤时,使⽤视图可以⼤⼤提⾼效率。
⽽且,视图中的数据会随着原表的变化⾃动更新。视图归根到底就是SELECT语句,所谓“参照视图”也就是“执⾏SELECT语句”的意思,因此可以保证数据的最新状态。这也
是将数据保存在表中所不具备的优势。
法则 2
应该将经常使⽤的SELECT语句做成视图。
⼆、创建视图的⽅法
创建视图需要使⽤CREATE VIEW语句,其语法如下所⽰。
KEYWORD
CREATE VIEW语句
db2数据库sql语句
语法 1 创建视图的CREATE VIEW语句
CREATE VIEW 视图名称(<;视图列名1>, <;视图列名2>, ……)
AS
<select语句>
SELECT语句需要书写在AS关键字之后。SELECT语句中列的排列顺序和视图中列的排列顺序相同,SELECT语句中的第 1 列就是视图中的第 1 列,SELECT语句中的第 2 列就是视图中的第 2 列,以此类推。视图的列名在视图名称之后的列表中定义。
备忘
接下来,我们将会以此前使⽤的Product(商品)表为基础来创建视图。如果⼤家已经根据之前章节的内容更新了Product表中的数据,请在创建视图之前将数据恢复到初始状态。操作步骤如下>所⽰。
①删除Product表中的数据,将表清空
DELETE FROM Product;
②执⾏代码清单 6()中的 SQL 语句,将数据插⼊到空表Product中
下⾯就让我们试着来创建视图吧。和此前⼀样,这次我们还是将Product表(代码清单 2)作为基本表。
代码清单 2 ProductSum视图
这样我们就在数据库中创建出了⼀幅名为ProductSum(商品合计)的视图。请⼤家⼀定不要省略第 2 ⾏的关键字AS。这⾥的AS与定义别名时使⽤的AS并不相同,如果省略就会发⽣错误。虽然很容易混淆,但是语法就是这么规定的,所以还是请⼤家牢记。
接下来,我们来学习视图的使⽤⽅法。视图和表⼀样,可以书写在SELECT语句的FROM⼦句之中(代码清单 3)。
代码清单 3 使⽤视图
执⾏结果
product_type | cnt_product
--------------+------------
⾐服        |          2
办公⽤品    |          2
厨房⽤具    |          4
通过上述视图ProductSum定义的主体(SELECT语句)我们可以看出,该视图将根据商品种类(product_type)汇总的商品数量(cnt_product)作为结果保存了起来。这样如果⼤家在⼯作中需要频繁进⾏汇总时,就不⽤每次都使⽤GROUP BY和COUNT函数写SELECT语句来从Product表中取得数据了。创建出视图之后,就可以通过⾮常简单的SELECT语句,随时得到想要的汇总结果。并且如前所述,Product表中的数据更新之后,视图也会⾃动更新,⾮常灵活⽅便。
之所以能够实现上述功能,是因为视图就是保存好的SELECT语句。定义视图时可以使⽤任何SELECT语句,既可以使⽤WHERE、GROUP BY、HAVING,也可以通过SELECT *来指定全部列。
使⽤视图的查询
在FROM⼦句中使⽤视图的查询,通常有如下两个步骤:
①⾸先执⾏定义视图的SELECT语句
②根据得到的结果,再执⾏在FROM⼦句中使⽤视图的SELECT语句
也就是说,使⽤视图的查询通常需要执⾏ 2 条以上的SELECT语句。
这⾥没有使⽤“2 条”⽽使⽤了“2 条以上”,是因为还可能出现以视图为基础创建视图的多重视图(图 2)。例如,我们可以像代码清单 4 那样以ProductSum为基础创建出视图ProductSumJim。
KEYWORD
多重视图
图 2 可以在视图的基础上创建视图
代码清单 4 视图ProductSumJim
-- 确认创建好的视图
SELECT product_type, cnt_product
FROM ProductSumJim;
执⾏结果
product_type | cnt_product
--------------+------------
办公⽤品    |          2
虽然语法上没有错误,但是我们还是应该尽量避免在视图的基础上创建视图。这是因为对多数 DBMS 来说,多重视图会降低 SQL 的性能。因此,希望⼤家(特别是刚刚接触视图的读者)能够使⽤单⼀视图。
法则 3
应该避免在视图的基础上创建视图。
除此之外,在使⽤时还要注意视图有两个限制,接下来会给⼤家详细介绍。
三、视图的限制①——定义视图时不能使⽤ORDER BY⼦句
虽然之前我们说过在定义视图时可以使⽤任何SELECT语句,但其实有⼀种情况例外,那就是不能使⽤ORDER BY⼦句,因此下述视图定义语句是错误的。
为什么不能使⽤ORDER BY⼦句呢?这是因为视图和表⼀样,数据⾏都是没有顺序的。实际上,有些 DBMS 在定义视图的语句中是可以使⽤ORDER BY⼦句的,但是这并不是通⽤的语法。因此,在定义视图时请不要使⽤ORDER BY⼦句。
法则 4
定义视图时不要使⽤ORDER BY⼦句。
四、视图的限制② ——对视图进⾏更新
之前我们说过,在SELECT语句中视图可以和表⼀样使⽤。那么,对于INSERT、DELETE、UPDATE这类更新语句(更新数据的 SQL)来说,会怎么样呢?
实际上,虽然这其中有很严格的限制,但是某些时候也可以对视图进⾏更新。标准 SQL 中有这样的规定:如果定义视图的SELECT语句能够满⾜某些条件,那么这个视图就可以被更新。下⾯就给⼤家列举⼀些⽐较具有代表性的条件。
①SELECT⼦句中未使⽤DISTINCT
②FROM⼦句中只有⼀张表
③未使⽤GROUP BY⼦句
④未使⽤HAVING⼦句
在前⼏章的例⼦中,FROM⼦句⾥通常只有⼀张表。因此,⼤家可能会觉得②中的条件有些奇怪,但其实FROM⼦句中也可以并列使⽤多张表。⼤家在学习完的操作之后就明⽩了。
其他的条件⼤多数都与聚合有关。简单来说,像这次的例⼦中使⽤的ProductSum那样,使⽤视图来保存原表的汇总结果时,是⽆法判断如何将视图的更改反映到原表中的。
例如,对ProductSum视图执⾏如下INSERT语句。
INSERT INTO ProductSum VALUES ('电器制品', 5);
但是,上述INSERT语句会发⽣错误。这是因为视图ProductSum是通过GROUP BY⼦句对原表进⾏汇总⽽得到的。为什么通过汇总得到的视图不能进⾏更新呢?
视图归根结底还是从表派⽣出来的,因此,如果原表可以更新,那么视图中的数据也可以更新。反之亦然,如果视图发⽣了改变,⽽原表没有进⾏相应更新的话,就⽆法保证数据的⼀致性了。
使⽤前述INSERT语句,向视图ProductSum中添加数据(' 电器制品 ',5)时,原表Product应该如何更新才好呢?按理说应该向表中添加商品种类为“电器制品”的 5 ⾏数据,但是这些商品对应的商品编号、商品名称和销售单价等我们都不清楚(图 3)。数据库在这⾥就遇到了⿇烦。
图 3 通过汇总得到的视图⽆法更新
法则 5
视图和表需要同时进⾏更新,因此通过汇总得到的视图⽆法进⾏更新。
能够更新视图的情况
像代码清单 5 这样,不是通过汇总得到的视图就可以进⾏更新。
代码清单 5 可以更新的视图
对于上述只包含办公⽤品类商品的视图ProductJim来说,就可以执⾏类似代码清单 6 这样的INSERT语句。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。