虚拟视图是由其他其他关系上的查询所定义的一种关系。虚拟视图并不在数据库中存储,但可对其进行查询,就好像它被存储在数据库中一样。查询处理器会在执行查询时用视图的定义来替换视图。
试图也可以被物化,即它们从数据库中定期的进行构造并存储。物化可以加快查询的执行,一种典型的“物化视图”就是索引。
CREATE VIEW <视图名> AS <视图定义>;
例如:有个关系如下:
Movies(title, year, length, name, producer)
要在其上创建一个视图,包括2018年的电影片名和年份,可以按如下定义:
CREATE VIEW viewMovies(viewTitle, viewName) AS
SELECT title, name
FROM Movies
WHERE year = 2018;
试图可以向被真正存储的表一样来查询。查询中可以同时使用视图和基本表。如:
SELECT DISTINCT starName
FROM viewMovies, StarIn
WHERE title = movieTile AND year = movieYear;
该查询等价于下面的查询:
SELECT DISTINCT atarName
FROM(SELECT title, year)
FROM Movies
WHERE year = 2018
)Pm, StarsIn
WHERE Pm.title = movieTitle AND Pm.year = movieYear;
大多数视图是不可以进行更新的,然而,对于一些很简单的视图----有时也称为可更新视图,可以把对视图的更新转变成一个等价的对基本表的更新,更新的操作最终作用在基本表上。此外,“替换”触发器可以将视图上的更新转变成基本表上的更新。这种方式能够强制对任何视图进行更新。
DROP VIEW viewMovie;
删除视图后不能再对视图进行更新、查询等操作,但是删除视图并不会影响到原基本表中的数据。
但是删除基本表后,也会使得在此基本表上建立的视图失效。
SQL允许对这样的视图进行更新操作:该视图是从单一关系R(R本身也可能是一个可更新视图)选取出(用SELECT关键字,而非SELECT DISTINCT)的一些属性组成。这里有三个要点:
当一个视图上定义了触发器时,触发器会拦截任何试图对视图进行修改的操作,并且将替代它们执行任何数据库设计者认为合适的操作。例如:
CREATE VIEW viewMovies(viewTitle, viewName) AS
SELECT title, name
FROM Movies
WHERE year = 2018;
当我们对这个视图进行插入操作时,系统不能判断year是否为2018,所以插入后的Movies表中year属性为NULL。
这时可以使用触发器:
CREATE TRIGGER viewMoviesInsert
INSTEAD OF INSERT ON viewMovies
REDERENCING NEW ROW AS NewRow
FOR EACH ROW
INSERT INTO Movies(title, name, year)
VALUES(NewRow.title, NewRow.name, 2018);
索引是一种数据结构,它能提高在属性A上查找某个特定值的效率。可以把索引认为是一棵二叉查找树中的键值对,键是属性A中可能含有的一个值,值是属性A上具有该值的元组集的存放位置。典型的DBMS使用B+树实现索引。注意:索引的键可以来自关系的任何一个属性或属性集,而不必是建立索引的关系的键属性。
当关系变得很大时,通过扫描关系中的所有元组查找那些可能数量很少的匹配元组代价太高。比如Movies中存有100000部电影,但大约只有200部是1990年制作的。
这时可以在Movies表的year属性上创建一个索引,因为索引是有序的而且不需要读取表中其他属性的信息,所以查找1990年电影的效率会大大提高。
CREATE INDEX yearIndex ON Movies(year);
选择创建哪个索引要求数据库设计者做一个开销上的分析。实际上索引的选择是衡量数据库设计成败的一个重要因素。设计索引时要考虑以下两个重要因素:
通常,关系上最有用的索引是其键上的索引,原因有两个:
在一些情况下,索引会失效,也就是系统弃用索引的情况:
1、对单属性建立索引,查询时使用多个属性。
CREATE INDEX myIndex ON Movies(year);
SELECT name
FROM Movies
WHERE year = 2018 AND length>120;
2、对属性集建立索引,使用不当会失效。
比如有一个索引:
CREATE INDEX myIndex ON Example(a,b,c);
当条件为a 或 a,b 或 a,b,c 时都可以使用索引,但是当条件为b,c时将不会使用索引。
3、对索引列运算,运算包括(+、-、*、/、!、<、>、%、like'%_'(%放在前面)、or、in、exist等),导致索引失效。
4、使用SQL内置函数时,作为内置函数参数的属性不会使用索引。
CREATE INDEX myIndex ON Movies(year);
SELECT name
FROM Movies
WHERE MAX(year)<2017;
6、使用表查询速度更快。
因为使用索引就是为了提高查询效率,如果DBMS判断通过表查询速度更快,就不会使用索引。
我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2zv8nkixjlog8