视图的基础表可以是基本表、临时表或其他视图。
视图是虚拟表或导出表,有别于基本表或临时表。
DBMS只是将视图存储为SELECT语句,而不是数据值的集合,从而防止数据冗余。
在SQL语句中用到时,视图才被动态创建。语句运行则存在,语句结束则消失。
视图是指定的数据列和数据行的集合,能使用实际表的地方几乎都可以使用视图。
通过视图查询没有限制。在某些情况下,视图更新引起的数据的变化可以被传递到基本表。
SQL程序员通常使用视图为数据库应用程序的终端用户展示数据。视图具有以下好处。
简化数据访问。视图隐藏了数据的复杂性并简化了语句,于是用户在视图上可以比直接在基本表上更容易地执行操作。如果创建了复杂视图--包含了多个基本表、联结和子查询--用户可以查询这个视图而不必理解其中复杂的关系,甚至不关心视图涉及哪些基本表。
自动更新。当基本表被更新后,所有引用这个表的视图都自动改变。例如,如果在表authors插入表示一个新作者的行,则所有在表authors上定义的视图将自动显示这个新作者。没有视图,DBMS将不得不存储检索来的数据以保持同步,所以这种模式节约硬盘空间并防止冗余。
增强安全性。视图最有用的是通过对基础表的过滤来对用户隐藏数据。假定表employees包含列salary和列commission。如果创建基于employees的视图不含这两列而包含其他无关紧要的列(如email_address),数据库管理员就可以授权用户查看视图而不查看基础表,这样就避免了人们因好奇而查看工资数据。
逻辑上数据独立。基本表提供数据库的真实视图。当使用SQL创建数据库应用时,如果不想向最终用户展示真实视图,就可以使用针对应用的虚拟视图。虚拟视图隐藏了数据库与应用无关的部分(整个表或某些行与列)。因此,用户在与虚拟视图交互。它尽管独立,却是从基本表的真实视图导出的。
在创建视图时,要重点考虑以下方面:
视图命名遵循表命名的规则。
视图名称在一个模式(或数据库)中必须唯一。它们不能和别的表名或视图重名。
视图中的列名默认继承自基础表。可以使用AS来给视图列不同的名称。
如果与视图中的另一列同名(通常是因为视图定义包含了联结,其中两个或多个基础表的列名相同),则必须为该列指定新名。
视图中定义的列可以是简单列引用、字面量或包含计算或聚合函数的表达式。
在一些DBMS中,如果列来自数学表达式、内置函数或字面量,则必须显式指明视图中的列名。
视图列的数据类型继承它所源自的列或表达式。
一些DBMS不允许在临时表上创建视图。
除了ORDER BY子句通常是被禁止的,几乎所有有效的SELECT语句都可以定义视图。
用视图可表示一些别无他法运行的查询。例如,可以定义联结GROUP BY视图和基础表的视图,或定义联结UNION视图和基本表的视图。
视图不能引用自身,因为它还不存在。
视图可以按不同于基础表中的格式展示数据。
因为视图不存储数据,DBMS必须在每次引用时执行它们。复杂的视图,尤其是嵌套视图,可能严重地降低效率。
创建视图语法:
- CREATE VIEW view [(view_columns)]
- AS select_statement;
view是要创建的视图的名称。数据库中视图的名称必须唯一。
view_columns是可选项,带括号的一个或(逗号分隔的)多个列名。在view_columns中的列数量必须与select_statement中的SELECT子句中的列数量相同。
当select_statement语句中的列源自一个算数表达式、函数或字面量时,就要指明view_ columns。列名也可以通过select_statement的AS子句指定。在一个视图中列名必须唯一。select_statement是指明视图所依据的行与列的SELECT语句。select_statement可以任意复杂且使用多个表和视图。ORDER BY子句通常是被禁止的。
例如:创建多表关联的视图
CREATE VIEW VI_INFO AS
(select distinct ge.code,ge.NAME,ge.CODE,ge.NAME,'GE' as TYPE
from tbl_GE ge
union all
select distinct cu.code,cu.NAME,cu.CODE,cu.NAME,'CU' as TYPE
from tbl_CU cu
union all
select distinct eq.code,eq.NAME,eq.CODE,eq.NAME,'EQ' as TYPE
from tbl_EQ eq
)
例如:创建视图列出那些居住在有出版社的城市的作者
CREATE VIEW cities (au_id, au_city, pub_id, pub_city)
AS
SELECT a.au_id, a.city, p.pub_id, p.city
FROM authors a
INNER JOIN publishers p
ON a.city = p.city;
例如:创建视图,按某一出版社图书的不同类型列出总收入(=价格×销量)
CREATE VIEW revenues (Publisher, BookType, Revenue)
AS
SELECT pub_id, type, SUM(price * sales)
FROM titles
GROUP BY pub_id, type;