第9章 视图

本章包括

◆ 视图的介绍

◆ 加密视图

◆ 检查视图的数据变动

◆ 为视图重命名

◆ 创建、查看、修改与删除视图

◆ 将视图与架构绑定

◆ 编辑视图中的记录

视图是一个虚拟的表,该表中的记录是由一个查询语句执行后所得到的查询结果构成。与表一样,视图也是由字段和记录组成,只是这些字段和记录来源于其他被引用的表或视图,所以视图并不是真实存在的,而是一张虚拟的表。视图中的数据同样也不是存在于视图中,而是存在于被引用的数据表中,当被引用的数据表中的记录内容改变时,视图中的记录内容也会随之改变。

9.1 视图简介

先举一个例子,在Northwind数据库中,如果要查看一个订单是由哪个雇员签订的、签订的时间是什么时候、买了什么产品、价格是多少、由谁来送货、送货的地址是什么等内容,那么就要从“产品”、“订单”、“订单明细”、“雇员”和“运货商”5个表中查询记录,其查询代码如下:

    SELECT订单.订单ID, 雇员.姓氏,雇员.名字,产品.产品名称,
        订单明细.单价,订单明细.数量,订单明细.折扣,运货商.公司名称,
        订单.货主名称,订单.货主地址,订单.货主城市,订单.订购日期,
        订单.发货日期
    FROM订单INNER JOIN
          订单明细ON订单.订单ID=订单明细.订单ID INNER JOIN
          雇员ON订单.雇员ID=雇员.雇员ID INNER JOIN
          产品ON订单明细.产品ID=产品.产品ID INNER JOIN
          运货商ON订单.运货商=运货商.运货商ID

查询结果如图9.1所示。如果要查询具体某一个订单的详细内容,还要在其后增加一个“WHERE订单.订单ID=”语句。

图9.1 执行查询语句后的结果

如果经常需要查询相同的字段内容(只是条件不同,例如上例中可能只是订单的ID号不同而已),每次都重复地写这么一大串相同的代码,无疑会增加工作量和影响工作效率。

再看图9.1所示结果,其显示出来的界面与在SQL Server Management Studio中打开一个表的界面是否十分相似?如果将这个查询的结果集视为一个表,那么这个表就是一个视图。下面是将该查询结果创建成视图的代码:

    CREATE VIEW订单详细视图
    AS
    SELECT订单.订单ID, 雇员.姓氏,雇员.名字,产品.产品名称,
        订单明细.单价,订单明细.数量,订单明细.折扣,运货商.公司名称,
        订单.货主名称,订单.货主地址,订单.货主城市,订单.订购日期,
        订单.发货日期
    FROM订单INNER JOIN
          订单明细ON订单.订单ID=订单明细.订单ID INNER JOIN
          雇员ON订单.雇员ID=雇员.雇员ID INNER JOIN
          产品ON订单明细.产品ID=产品.产品ID INNER JOIN
          运货商ON订单.运货商=运货商.运货商ID

创建完视图之后,如果还要以同样的条件进行查询,只要输入以下一行代码就可以得到查询结果:

    SELECT * FROM订单详细视图

即使要查询某个订单的详细情况,也只要输入以下代码,而不用输入那么一长串代码了。

    SELECT * FROM订单详细视图
            WHERE订单ID=10248

视图具备了数据表的一些特性,数据表可以完成的功能,例如查询、修改(虽然在修改记录时有些限制)、删除等操作,在视图中都可以完成。同时,视图也和数据表一样能成为另一个视图所引用的表。使用视图有以下几个优点:

简化查询语句:通过视图可以将复杂的查询语句变得很简单。

增加可读性:由于在视图中可以只显示有用的字段,并且可以使用字段别名,从而方便用户浏览查询的结果。

方便程序的维护:如果应用程序使用视图来存取数据,那么当数据表的结构发生改变时,只需要更改视图存储的查询语句即可,不需要更改程序。

增加数据的安全性和保密性:针对不同的用户,可以创建不同的视图,此时的用户只能查看和修改其所能看到的视图中的数据,而真正的数据表中的数据(甚至连数据表)都是不可见(不可访问)的,这样可以限制用户浏览和操作的数据内容。另外,视图所引用的表的访问权限与视图的权限设置也是相互不影响的。

注意 视图是个虚拟的表,其存储的是查询语句而不是数据。视图中的数据都存储在其引用的数据表中,除非在视图中建立了索引。

9.2 创建视图

创建视图与创建数据表一样,可以使用SQL Server Management Studio和T-SQL语句两种方法,下面分别介绍这两种方法。

9.2.1 在SQL Server Management Studio中创建视图

在SQL Server Management Studio中创建视图的方法与创建数据表的方法不同,下面举例说明如何在SQL Server Management Studio中创建视图。

step 1 启动SQL Server Management Studio,连接到本地默认实例,在【对象资源管理器】窗格中,选择本地数据库实例→【数据库】→【Northwind】→【视图】选项。

step 2 右击【视图】选项,在弹出的快捷菜单中选择【新建视图】选项。

step 3 弹出图9.2所示的视图设计界面,并自动打开【添加表】对话框,可以将要引用的表添加到视图设计界面中。在本例中,添加“产品”、“订单”、“订单明细”、“雇员”和“运货商”5个表。

图9.2 视图设计界面

step 4 添加完数据表之后,单击【关闭】按钮,返回到图9.3所示的视图设计界面。如果还要添加新的数据表,可以右击【关系图】窗格的空白处,在弹出的快捷菜单中选择【添加表】选项,则会弹出图9.2中所示的【添加表】对话框,然后继续为视图添加引用表或视图。如果要移除已经添加的数据表或视图,可以在【关系图】窗格里右击要移除的数据表或视图,在弹出的快捷菜单里选择【移除】选项,或选中要移除的数据表或视图后,直接按【Delete】键移除。

图9.3 视图设计

step 5 在【关系图】窗格中,可以建立表与表之间的JOIN…ON关系。例如,“产品”表的“产品ID”与“订单明细”表中的“产品ID”相等,那么只要将“产品”表中的“产品ID”字段拖放到“订单明细”表中的“产品ID”字段上即可,此时两个表之间将会显示一根连线。

step 6 在【关系图】窗格中选择数据表字段前的复选框,可以设置视图要输出的字段。同样,在【条件】窗格中也可设置要输出的字段。

step 7 在【条件】窗格中还可以设置要过滤的查询条件。

step 8 设置完成后,SQL语句会显示在【SQL】窗格中,这个Select语句也就是视图所要存储的查询语句。

step 9 所有查询条件设置完毕之后,单击【执行SQL】按钮,检查Select语句运行是否正确。

step 10 在一切测试都正常之后,单击【保存】按钮,在弹出的对话框里输入视图名称,再单击【确定】按钮完成操作。

9.2.2 使用Create view语句创建视图

9.2.2.1 基本语法

用T-SQL的Create view语句可以创建视图,其语法为:

    CREATE VIEW [ schema_name . ] view_name                       --架构名.视图名
        [ (column [ , ...n ] ) ]                                       --列名
    [ WITH <view_attribute> [ , ...n ] ]
    AS select_statement [ ; ]                                        --搜索语句
    [ WITH CHECK OPTION ]          --强制修改语句都必须符合在select_ statement中设置的条件
    <view_attribute> ::=
    {
        [ ENCRYPTION ]                                                  --加密
        [ SCHEMABINDING ]                                              --绑定架构
        [ VIEW_METADATA ]     }                                   --返回有关视图的元数据信息
9.2.2.2 参数说明

Create view语句的参数如下:

schema_name:视图所属架构名。

view_name:视图名。

column:视图中所使用的列名,一般只有列是从算术表达式、函数或常量派生出来的或者列的指定名称不同于来源列的名称时,才需要使用。

select_statement:搜索语句。

WITH CHECK OPTION:强制针对视图执行的所有数据修改语句都必须符合在select_statement中设置的条件。

ENCRYPTION:加密视图。

SCHEMABINDING:将视图绑定到基础表的架构。

VIEW_METADATA:指定为引用视图的查询请求浏览模式的元数据时,SQL Server实例将向DB-Library,ODBC和OLE DB API返回有关视图的元数据信息,而不返回基表的元数据信息。

9.2.2.3 简单用法

例一:创建简单视图。

创建一个视图,用于查看产品、类别和供应商,其代码如下:

    --创建视图
    CREATE VIEW view_例一
        AS
        SELECT产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
    GO
    --查看视图
    SELECT * FROM view_例一
    GO

其运行结果如图9.4所示。

图9.4 显示视图

9.2.2.4 给视图字段加上别名

例二:给视图加上别名。

创建一个视图,用于查看产品、类别和供应商,并修改其字段名,其代码如下:

    CREATE VIEW view_例二(产品编号,产品名称,产品类别,供应商名称)
        AS
        SELECT产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
    GO
    SELECT * FROM view_例二
    GO

其运行结果如图9.5所示,视图的字段名与图9.4中所显示的不一样。

图9.5 为视图加上字段别名

9.2.2.5 创建视图时的注意事项

在用Create view语句创建视图时,Select子句里不能包括以下内容:

◆ 不能包括Compute和Compute by子句。

◆ 不能包括Order by子句,除非在Select子句里有top子句。

◆ 不能包括option子句。

◆ 不能包括into关键字。

◆ 不能引用临时表或表变量。

例三:错误的创建视图方式。

创建一个视图,查看最新100项产品的产品名称、类别名称和供应商。以下的代码是错误的:

    CREATE VIEW view_例三
        AS
        SELECT产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
        ORDER BY产品.产品ID DESC                  --不能在Select子句里使用Order by子句

只有在创建好视图后才可以使用Order by子句,例如:

    SELECT top 100 * FROM view_例三
        ORDER BY产品ID DESC

但是,如果在Select子句里指定了top,可以使用Order by子句。以下代码就是正确的:

    CREATE VIEW view_例三
        AS
        SELECT top 100 产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
        ORDER BY产品.产品ID DESC

9.3 查看与修改视图

由于视图与数据表很类似,所以在查看视图内容方面,与查看数据表内容十分相似,但在修改视图方面就会有些区别。

9.3.1 查看视图

在SQL Server Management Studio中查看视图内容的方法与查看数据表内容的方法几乎一致,下面以查看视图“view_例一”为例介绍如何查看视图:

step 1 启动SQL Server Management Studio,连接到本地默认实例,在【对象资源管理器】窗格里,选择本地数据库实例→【数据库】→【Northwind】→【视图】→【view_例一】选项。

step 2 右击【view_例一】选项,在弹出的快捷菜单中选择【查看视图】选项,出现图9.6所示的窗格,该界面与查看数据表的界面几乎一致,在此不再赘述。

图9.6 查看视图

在T-SQL语句里,使用Select语句可以查看视图的内容,其用法与查看数据表内容的用法一样,区别是把数据表名改为视图名,在此不再赘述。

9.3.2 在SQL Server Management Studio中修改视图

使用SQL Server Management Studio修改视图事实上只是修改该视图所存储的T-SQL语句,下面以修改视图“view_例一”为例介绍如何在SQL Server Management Studio中修改视图:

step 1 启动SQL Server Management Studio,连接到本地默认实例,在【对象资源管理器】窗格中,选择本地数据库实例→【数据库】→【Northwind】→【视图】→【view_例一】选项。

step 2 右击【view_例一】选项,在弹出的快捷菜单中选择【设计】选项,出现如图9.7所示的界面。该界面与创建视图的界面相似,其操作也十分类似,在此不再赘述。

图9.7 修改视图

step 3 修改完后一定要保存。

9.3.3 使用Alter view语句修改视图

使用T-SQL的Alter view语句可以修改视图,其语法代码如下:

    ALTER VIEW [ schema_name . ] view_name [ ( column [ , ...n ] ) ]
    [ WITH <view_attribute> [ , ...n ] ]
    AS select_statement [ ; ]
    [ WITH CHECK OPTION ]
    <view_attribute> ::=
    {
        [ ENCRYPTION ]
        [ SCHEMABINDING ]
        [ VIEW_METADATA ]     }

从上面代码可以看出,Alter view语句的语法和Create view语句完全一样,只不过是以“alter view”开头。下面举例说明Alter view语句的用法。

例四:修改视图。

修改视图“view_例三”,只查看最新的50个产品内容,其代码如下:

    ALTER VIEW view_例三
        AS
        SELECT top 50 产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
        ORDER BY产品.产品ID DESC

9.4 加密视图

在SQL Server 2008中,每个数据库的系统视图里都有一个名为“INFORMATION_SCHEMA. VIEWS”的视图,该视图里记录了数据库中所有视图的信息,使用“SELECT * FROM INFORMATION_SCHEMA.VIEWS”可以查看该视图内容,如图9.8所示。

图9.8 查看视图内容

如果不想让别人看到视图里的内容,可以使用with encryption参数为视图加密。

例五:加密视图。

创建一个加密视图,内容与例三中的视图一样,其代码如下:

    CREATE VIEW view_例五
        WITH ENCRYPTION
        AS
        SELECT top 50 产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
        ORDER BY产品.产品ID DESC

再使用“SELECT * FROM INFORMATION_SCHEMA.VIEWS”查看视图内容,其结果如图9.9所示,在“view_例五”记录上显示的视图内容为NULL,而事实上,“view_例五”视图的内容并不为NULL,只是加密后用户无法查看而已。

图9.9 加密后的视图内容

创建完加密视图之后,在SQL Server Management Studio中也不能对其进行修改。如图9.10所示,“view_例五”视图前的小图标与其他视图不同,上面有一把小锁,代表视图已被加密。右击该视图名,在弹出的快捷菜单中【设计】选项是灰色的,不能进行修改。

图9.10 加密后的视图

虽然在SQL Server Management Studio中不能修改加密视图,但是并不意味着加密视图就不能被修改,使用Alter view语句可以修改加密视图。因为使用Alter view语句修改视图和使用SQL Server Management Studio修改视图不同,它不需要先显示视图的代码。

例六:修改加密的视图。

修改加密的“view_例五”视图,取消加密,其代码如下:

    ALTER VIEW view_例五
        AS
        SELECT top 50 产品.产品ID,产品.产品名称,类别.类别名称,供应商.公司名称
            FROM产品
            JOIN类别ON产品.类别ID=类别.类别ID
            JOIN供应商ON产品.供应商ID=供应商.供应商ID
        ORDER BY产品.产品ID DESC

注意 虽然视图加密后看不到其存储的Select语句,但并不影响对它的使用。

9.5 限制视图所用的表或视图不能更改设计和删除

由于视图和数据表是数据库中独立的两种对象,虽然视图要引用数据表,但是当引用的数据表被删除或修改时,视图本身并不会被删除或修改,因此往往在删除数据表之后,会引起视图运行错误。如果在创建视图时使用了with schemabinding参数,就可以防止引用的数据表或视图被删除或修改。

例七:限制视图所用的表。

创建两个数据表,再创建一个带with schemabinding参数的引用这两个数据表的视图,然后试图修改和删除数据表。其代码如下:

    --创建两个数据表
    CREATE TABLE例七_1(
        id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
        username nchar(10) NULL
    )
    CREATE TABLE例七_2(
        id int IDENTITY(1,1) NOT NULL PRIMARY KEY,
        newname nchar(10) NULL
    )
    GO
    --创建视图
    CREATE VIEW view_例七
        WITH SCHEMABINDING
        AS
        SELECT例七_1.username,例七_2.newname
            FROM dbo.例七_1 JOIN dbo.例七_2
                ON例七_1.id=例七_2.id
    GO
    --修改数据表
    PRINT ' '
    ALTER TABLE例七_1
        ALTER COLUMN username nvarchar(100)
    GO
    PRINT ' '
    ALTER TABLE例七_2
        ALTER COLUMN newname nvarchar(100)
    GO
    --删除数据表
    PRINT ' '
    DROP TABLE例七_1
    GO
    PRINT ' '
    DROP TABLE例七_2
    GO

其运行结果如图9.11所示。

图9.11 限制视图所用的表不能更改设计和删除

在图9.11中可以看出,无论是修改哪个数据表或删除数据表都会出现错误信息,不允许修改或删除。再仔细观察创建视图的代码,有几个必须要注意的地方:

◆ 只有使用WITH SCHEMABINDING之后,才能限制被引用的数据表或视图不被修改或删除。

◆ 使用了WITH SCHEMABINDING参数后,在Select语句中,不能使用Select *来代表所有字段,必须指定字段名。

◆ 使用了WITH SCHEMABINDING参数后,在Select语句里所用到的数据表或视图名,必须用Owner.object方式来表示。

9.6 检查视图的数据变动

使用视图还可以达到约束的功能,当视图中有新记录插入或被修改时,若不符合视图的创建条件时,将会被拒绝执行。要实现该功能,需要使用WITH CHECK OPTION参数。

例八:创建符合条件的视图。

创建一个视图,要求在视图内的所有产品的单价必须超过20元。其代码如下:

    CREATE VIEW view_例八
        AS
        SELECT产品ID,产品名称,单价
            FROM产品
            WHERE单价> $20
        WITH CHECK OPTION

如果此时要将视图中编号为4的记录的单价改为16,那么运行以下代码将会出错:

    UPDATE view_例八
        SET单价=$16
        WHERE产品ID=4

因为在视图“view_例八”中,已经用“WITH CHECK OPTION”设定了数据检查,在对该视图里的数据进行操作时,如果不能符合当初创建视图时设定的“单价> $20”的条件,则不能执行该操作。但是在该视图所引用的数据表里,还是可以执行的,例如以下代码就能成功执行:

    UPDATE  产品
        SET单价=$16
        WHERE产品ID=4

9.7 编辑视图中的记录

由于视图与数据表十分类似,所以对视图的操作与数据表也十分类似,但是编辑视图中的记录还是会有一些限制,请看下面的介绍。

9.7.1 编辑视图中的记录的限制

要编辑视图中的记录,以下几点是必须要注意的:

◆ Timestamp和Binary类型的字段不能编辑。

◆ 如果字段的值是自动产生的,例如带标识字段、计算字段等,则不能编辑。

◆ 经编辑的字段内容必须符合引用表的字段定义。

◆ 在引用表中可以不输入内容的字段,例如可以为NULL或有默认值的字段,在视图中也可以不输入内容。

◆ 在视图中修改的字段最好是同一个引用表中的字段,避免出现一些未知的结果。

◆ 在视图中修改的字段内容,实际上就是在数据表中修改的字段内容。

9.7.2 在SQL Server Management Studio中操作视图记录

在SQL Server Management Studio中,可以像编辑数据表记录内容一样编辑视图里的记录内容。其操作如下:

step 1 打开视图。

step 2 找到要修改的记录,在记录上直接修改字段内容,修改完毕之后,只需将光标从该记录上移开,定位到其他记录上,SQL Server就会将修改的记录保存。

在视图中插入记录的方法与在数据表中插入记录的方法类似:

step 1 打开视图。

step 2 定位到最后一条记录下面,有一条所有字段都为NULL的记录,在此可以输入新记录的内容。

一般来说,不建议在视图中插入新记录,因为在视图中往往显示的是多个表中的几个字段,而在插入新记录时,除了要指定这些字段的内容之外,还可能要输入其他字段内容才能完成该数据表的记录插入工作。

例如,在例八中创建的视图中,如果要在其中插入一条记录,在视图中只能输入产品ID、产品名称和单价三个字段的内容,然而插入一条产品记录,还要包括供应商ID、类别ID两个字段内容,这个在视图中无法提供,所以在视图中插入记录将会失败。

在SQL Server Management Studio中删除视图记录的方法如下:

step 1 打开视图。

step 2 右击要删除的记录,在弹出的快捷菜单中选择【删除】选项,然后在弹出的警告对话框里单击【是】按钮,完成删除操作。

同样,在视图中删除记录时,如果会同时在多个数据表中删除记录,也会失败,因为SQL Server无法判断要删除的是哪个数据表里的哪条记录。

9.7.3 使用lnsert, Update和Delete语句操作视图记录

可以使用T-SQL语言中的Insert,Update和Delete语句来操作视图的记录,这些语句与操作数据表的语句基本相同,只要将原来输入数据表名的地方改为视图名即可。在例八中出现过如下代码,就是更新视图记录的代码。

    UPDATE view_例八
        SET单价=$16
        WHERE产品ID=4

在该视图里删除记录的代码也可以按如下方法编写:

    DELETE view_例八
        WHERE产品ID=4

在视图中插入记录的方法:

    INSERT view_例八(产品名称,单价)
        VALUES (’白菜’, $1)

事实上,该Insert语句在执行时会失败,因为它并没有提供插入产品记录所需要的所有必须提供的字段内容。

9.8 删除视图

当一个视图不再需要使用时,可以将其删除。

9.8.1 在Management Studio中删除视图

下面以删除“view_例七”为例,介绍如何在SQL Server Management Studio中删除视图:

step 1 启动SQL Server Management Studio,连接到本地数据库默认实例。

step 2 在【对象资源管理器】窗格里展开树形目录,定位到【view_例七】选项。右击【view_例七】选项,在弹出的快捷菜单里选择【删除】选项。

step 3 在弹出的【删除对象】对话框里可以看到要删除的视图名称,单击【确定】按钮完成操作。

9.8.2 使用Drop view语句删除视图

在T-SQL语言里,用Drop view语句可以删除视图,其语法代码为:

    DROP VIEW [ schema_name . ] view_name [ ..., n ] [ ; ]

例如,删除“view_例一”视图的语句:

    DROP VIEW view_例一

也可以一次删除多个视图,例如:

    DROP VIEW view_例二,view_例三

9.9 为视图重命名

在SQL Server Management Studio中为视图重命名的方法如下:

step 1 启动SQL Server Management Studio,连接上数据库实例,展开【对象资源管理器】窗格里的树形目录,定位到要改名的视图上。

step 2 右击要改名的视图,在弹出的快捷菜单里选择【重命名】选项。

step 3 输入新的视图名,再按【Enter】键完成操作。

也可以使用存储过程sp_rename来修改视图名,例如:

    exec sp_rename ' view_例五’, ' view_例五_1'

9.10 小结

视图是一个虚拟的表,该表中的记录是由一个查询语句执行后得到的查询结果所构成。因此,视图中存储的只是一个查询语句,视图中的数据并不是存在于视图中,而是存在于被引用的数据表中。当被引用的数据表中的记录内容改变时,视图中的记录内容也会随之改变。

创建完视图之后,查看、修改和删除视图的方法与查看、修改和删除数据表的方法如出一辙。要熟练掌握创建、查看、修改和删除视图的方法。

第10章将会介绍如何使用存储过程。