Transact-SQL 参考

CREATE VIEW

创建一个虚拟表,该表以另一种方式表示一个或多个表中的数据。CREATE VIEW 必须是查询批处理中的第一条语句。

语法

CREATE VIEW [ < database_name > .] [ < owner > .] view_name [ ( column [ ,...n ] ) ]
[ WITH < view_attribute > [ ,...n ] ]
AS
select_statement
[ WITH CHECK OPTION ]

< view_attribute > ::=

    { ENCRYPTION | SCHEMABINDING | VIEW_METADATA }

参数

view_name

是视图的名称。视图名称必须符合标识符规则。可以选择是否指定视图所有者名称。

column

是视图中的列名。只有在下列情况下,才必须命名 CREATE VIEW 中的列:当列是从算术表达式、函数或常量派生的,两个或更多的列可能会具有相同的名称(通常是因为联接),视图中的某列被赋予了不同于派生来源列的名称。还可以在 SELECT 语句中指派列名。

如果未指定 column,则视图列将获得与 SELECT 语句中的列相同的名称。

说明  在视图的各列中,列名的权限在 CREATE VIEW 或 ALTER VIEW 语句间均适用,与基础数据源无关。例如,如果在 CREATE VIEW 语句中授予了 title_id 列上的权限,则 ALTER VIEW 语句可以将 title_id 列改名(例如改为 qty),但权限仍与使用 title_id 的视图上的权限相同。

n

是表示可以指定多列的占位符。

AS

是视图要执行的操作。

select_statement

是定义视图的 SELECT 语句。该语句可以使用多个表或其它视图。若要从创建视图的 SELECT 子句所引用的对象中选择,必须具有适当的权限。

视图不必是具体某个表的行和列的简单子集。可以用具有任意复杂性的 SELECT 子句,使用多个表或其它视图来创建视图。

在索引视图定义中,SELECT 语句必须是单个表的语句或带有可选聚合的多表 JOIN。

对于视图定义中的 SELECT 子句有几个限制。CREATE VIEW 语句不能:

因为 select_statement 使用 SELECT 语句,所以在 FROM 子句中指定 <join_hint> 和 <table_hint> 提示是有效的。有关更多信息,请参见 FROMSELECT

select_statement 中可以使用函数。

select_statement 可使用多个由 UNION 或 UNION ALL 分隔的 SELECT 语句。

WITH CHECK OPTION

强制视图上执行的所有数据修改语句都必须符合由 select_statement 设置的准则。通过视图修改行时,WITH CHECK OPTION 可确保提交修改后,仍可通过视图看到修改的数据。

WITH ENCRYPTION

表示 SQL Server 加密包含 CREATE VIEW 语句文本的系统表列。使用 WITH ENCRYPTION 可防止将视图作为 SQL Server 复制的一部分发布。

SCHEMABINDING

将视图绑定到架构上。指定 SCHEMABINDING 时,select_statement 必须包含所引用的表、视图或用户定义函数的两部分名称 (owner.object)。

不能除去参与用架构绑定子句创建的视图中的表或视图,除非该视图已被除去或更改,不再具有架构绑定。否则,SQL Server 会产生错误。另外,如果对参与具有架构绑定的视图的表执行 ALTER TABLE 语句,而这些语句又会影响该架构绑定视图的定义,则这些语句将会失败。

VIEW_METADATA

指定为引用视图的查询请求浏览模式的元数据时,SQL Server 将向 DBLIB、ODBC 和 OLE DB API 返回有关视图的元数据信息,而不是返回基表或表。浏览模式的元数据是由 SQL Server 向客户端 DB-LIB、ODBC 和 OLE DB API 返回的附加元数据,它允许客户端 API 实现可更新的客户端游标。浏览模式的元数据包含有关结果集内的列所属的基表信息。

对于用 VIEW_METADATA 选项创建的视图,当描述结果集中视图内的列时,浏览模式的元数据返回与基表名相对的视图名。

当用 VIEW_METADATA 创建视图时,如果该视图具有 INSERT 或 UPDATE INSTEAD OF 触发器,则视图的所有列(timestamp 除外)都是可更新的。请参见本主题后面的"可更新视图"。

注释

只能在当前数据库中创建视图。视图最多可以引用 1,024 列。

通过视图进行查询时,Microsoft® SQL Server™ 将检查以确定语句中任意位置引用的所有数据库对象是否都存在,这些对象在语句的上下文中是否有效,以及数据修改语句是否没有违反任何数据完整性规则。如果检查失败,将返回错误信息。如果检查成功,则将操作转换成对基础表的操作。

如果某个视图依赖于已除去的表(或视图),则当有人试图使用该视图时,SQL Server 将产生错误信息。如果创建了新表或视图(该表的结构与以前的基表没有不同之处)以替换除去的表或视图,则视图将再次可用。如果新表或视图的结构发生更改,则必须除去并重新创建该视图。

创建视图时,视图的名称存储在 sysobjects 表中。有关视图中所定义的列的信息添加到 syscolumns 表中,而有关视图相关性的信息添加到 sysdepends 表中。另外,CREATE VIEW 语句的文本添加到 syscomments 表中。这与存储过程相似;当首次执行视图时,只有其查询树存储在过程高速缓存中。每次访问视图时,都重新编译其执行计划。

在通过 numeric float 表达式定义的视图上使用索引所得到的查询结果,可能不同于不在视图上使用索引的类似查询所得到的结果。这种差异可能是由对基础表进行 INSERT、DELETE 或 UPDATE 操作时的舍入错误引起的。

创建视图时,SQL Server 保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的设置。使用视图时,将还原这些最初的设置。因此,当访问视图时,将忽略 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的所有客户端会话设置。

说明  SQL Server 是将空字符串解释为单个空格还是真正的空字符串取决于 sp_dbcmptlevel 的设置。如果兼容级别小于或等于 65,SQL Server 就将空字符串解释为单个空格。如果兼容级别等于或大于 70,则 SQL Server 就将空字符串解释为空字符串。有关更多信息,请参见 sp_dbcmptlevel

可更新视图

Microsoft SQL Server 2000 以两种方法增强可更新视图的类别:

如果视图没有 INSTEAD OF 触发器,或者视图不是分区视图,则视图只有满足下列条件才可更新:

INSERT、UPDATE 和 DELETE 语句在可以引用可更新视图之前,也必须如上述条件指定的那样满足某些限制条件。只有当视图可更新,并且所编写的 UPDATE 或 INSERT 语句只修改视图的 FROM 子句引用的一个基表中的数据时,UPDATE 和 INSERT 语句才能引用视图。只有当视图在其 FROM 子句中只引用一个表时,DELETE 语句才能引用可更新的视图。

分区视图

分区视图是通过对成员表使用 UNION ALL 所定义的视图,这些成员表的结构相同,但作为多个表分别存储在同一个 SQL Server 中,或存储在称为联合 SQL Server 2000 服务器的自主 SQL Server 2000 服务器组中。

例如,如果使 Customers 表数据分布在分别位于三个服务器上的三个成员表中(Customers_33Server1 上,Customers_66Server2 上,Customers_99Server3 上),将以下面的方法在 Server1 上定义分区视图:

--Partitioned view as defined on Server1
CREATE VIEW Customers
AS
--Select from local member table
SELECT *
FROM CompanyData.dbo.Customers_33
UNION ALL
--Select from member table on Server2
SELECT *
FROM Server2.CompanyData.dbo.Customers_66
UNION ALL
--Select from mmeber table on Server3
SELECT *
FROM Server3.CompanyData.dbo.Customers_99

一般情况下,如果视图为下列格式,则称其为分区视图:

SELECT <select_list1>
FROM T1
UNION ALL
SELECT <select_list2>
FROM T2
UNION ALL
...
SELECT <select_listn>
FROM Tn

分区视图的创建条件

  1. SELECT 列表
    • 成员表中的所有列应在视图定义的列列表中被选定。

    • 每个 select_list 中的同一序号位置上的列应属于同一类型,包括排序规则。列仅仅属于隐性可转换类型(如 UNION 的通常情况下)是不够的。

      另外,at least one 列(例如 <col>)必须以相同的序号位置出现在所有 SELECT 列表中。应这样定义 <col>:使成员表 T1,...,Tn 在 <col> 上分别定义 CHECK 约束 C1,...,Cn

      必须以下面的格式在表 T1 上定义约束 C1:

      C1 ::= < simple_interval > [ OR < simple_interval > OR ...]
      < simple_interval > :: = 
          < col > { < | > | <= | >= | = } 
          | < col > BETWEEN < value1 > AND < value2 >
          | < col > IN ( value_list )
          | < col > { > | >= } < value1 > AND
              < col > { < | <= } < value2 >
      
    • 约束应使 <col> 的任何给定值都能满足约束 C1,...,Cnat most one,这样,约束应形成一套不连接的或非重叠的间隔。定义不连接的约束的列 <col> 称为"分区列"。请注意分区列在基础表中可能有不同的名称。约束应处于"已启用"状态,以使它们满足分区列的上述条件。如果禁用了约束,则请使用 ALTER TABLE 的 WITH CHECK 选项或 CHECK constraint_name 选项重新启用约束检查。

      下面是有效约束集的示例:

      { [col < 10], [col between 11 and 20] , [col > 20] }
      { [col between 11 and 20], [col between 21 and 30], [col between 31 and 100] }
      
    • 在 SELECT 列表中不能多次使用同一列。
  2. 分区列
    • 分区列是表的 PRIMARY KEY 的一部分。

    • 不能是计算列。

    • 如果成员表中的同一列上存在多个约束,则 SQL Server 忽略所有约束且在确定视图是否为分区视图时不考虑这些约束。为满足分区视图的条件,在分区列上应只有一个分区约束。
  3. 成员表(或基础表 T1,...,Tn
    • 表可以是本地表,也可以是通过由四部分构成的名称或基于 OPENDATASOURCE 或 OPENROWSET 的名称引用的其它 SQL Server 中的表。(OPENDATASOURCE 和 OPENROWSET 语法可以指定表名,但不能指定直接传递查询。)有关更多信息,请参见 OPENDATASOURCEOPENROWSET

      如果一个或多个成员表是远程表,则视图称为 distributed partitioned view,并且适用附加条件。本节稍后将对其进行讨论。

    • 在用 UNION ALL 语句组合的表集中,同一个表不能出现两次。

    • 成员表不能在表中的计算列上创建索引。

    • 成员表在数目相同的列上应具有所有 PRIMARY KEY 约束。

    • 视图中的所有成员表应有相同的 ANSI 填充设置(使用 sp_configure user options 选项或 SET 选项设置)。

修改分区视图的条件

只有 SQL Server 2000 开发版和企业版允许在分区视图中进行 INSERT、UPDATE 和 DELETE 操作。若要修改分区视图,语句必须满足下列条件:

分布式分区视图的附加条件

对于分布式分区视图(当一个或多个成员表为远程表时),适用下列附加条件:

对于涉及可更新分区视图和远程表的 INSERT、UPDATE 和 DELETE 操作,忽略 SET ROWCOUNT 选项的设置。

当设置好成员表和分区视图的定义后,Microsoft SQL Server 2000 将生成智能的查询计划以便有效地访问成员表中的数据。通过使用 CHECK 约束定义,查询处理器在成员间映射键值的分布。当用户发出查询时,查询处理器将映射与 WHERE 子句中指定的值进行比较,然后生成使成员服务器间的数据传输量减到最少的执行计划。因此,虽然有些成员表可能位于远程服务器中,但是 SQL Server 2000 将解析分布式查询,使得必须传输的分布式数据量减到最少。有关 SQL Server 2000 如何解析分区视图查询的更多信息,请参见解析分布式分区视图

复制的考虑事项

为在复制所包含的成员表上创建分区视图,需要考虑下列事项:

权限

CREATE VIEW 权限默认授予 db_owner db_ddladmin 固定数据库角色成员。sysadmin 固定服务器角色成员和 db_owner 固定数据库角色成员可以将 CREATE VIEW 权限转让给其他用户。

若要创建视图,用户必须具有 CREATE VIEW 权限,还必须在视图所引用的表、视图和表值函数上具有 SELECT 权限,在视图所唤醒调用的标量值函数上具有 EXECUTE 权限。

另外,若要创建 WITH SCHEMABINDING 视图,用户必须在每个引用的表、视图和用户定义函数上具有 REFERENCES 权限。

示例
A. 使用简单的 CREATE VIEW

下例创建具有简单 SELECT 语句的视图。当需要频繁地查询列的某种组合时,简单视图非常有用。

USE pubs
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'titles_view')
   DROP VIEW titles_view
GO
CREATE VIEW titles_view
AS 
SELECT title, type, price, pubdate
FROM titles
GO
B. 使用 WITH ENCRYPTION

下例使用 WITH ENCRYPTION 选项并显示计算列、重命名列以及多列。

USE pubs
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'accounts')
   DROP VIEW accounts
GO
CREATE VIEW accounts (title, advance, amt_due)
WITH ENCRYPTION
AS 
SELECT title, advance, price * royalty * ytd_sales
FROM titles
WHERE price > $5
GO

下面是用来检索加密存储过程的标识号和文本的查询:

USE pubs
GO
SELECT c.id, c.text 
FROM syscomments c, sysobjects o
WHERE c.id = o.id and o.name = 'accounts'
GO

下面是结果集:

说明  text 列的输出显示在单独一行中。执行该存储过程时,下列信息将与 id 列信息出现在同一行中。

id          text                                                        
----------- ------------------------------------------------------------
661577395  
???????????????????????????????????????????????????????????????????????...

(1 row(s) affected)
C. 使用 WITH CHECK OPTION

下例显示名为 CAonly 的视图,该视图使得只对加利福尼亚州的作者应用数据修改。

USE pubs
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'CAonly')
   DROP VIEW CAonly
GO
CREATE VIEW CAonly
AS 
SELECT au_lname, au_fname, city, state
FROM authors
WHERE state = 'CA'
WITH CHECK OPTION
GO
D. 在视图中使用内置函数

下例显示包含内置函数的视图定义。使用函数时,必须在 CREATE VIEW 语句中为派生列指定列名。

USE pubs
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'categories')
   DROP VIEW categories
GO
CREATE VIEW categories (category, average_price)
AS 
SELECT type, AVG(price)
FROM titles
GROUP BY type
GO
E. 在视图中使用 @@ROWCOUNT 函数

下例使用 @@ROWCOUNT 函数作为视图定义的一部分。

USE pubs
IF EXISTS (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.VIEWS
      WHERE TABLE_NAME = 'myview')
   DROP VIEW myview
GO
CREATE VIEW myview
AS
   SELECT au_lname, au_fname, @@ROWCOUNT AS bar
   FROM authors
   WHERE state = 'UT'
GO
SELECT * 
FROM myview
F. 使用分区数据

下例使用名为 SUPPLY1SUPPLY2SUPPLY3SUPPLY4 的表,这些表对应于位于不同国家的四个办事处的供应商表。

--create the tables and insert the values
CREATE TABLE SUPPLY1 (
   supplyID INT PRIMARY KEY CHECK (supplyID BETWEEN 1 and 150),
   supplier CHAR(50)
   )
CREATE TABLE SUPPLY2 (
   supplyID INT PRIMARY KEY CHECK (supplyID BETWEEN 151 and 300),
   supplier CHAR(50)
   )
CREATE TABLE SUPPLY3 (
   supplyID INT PRIMARY KEY CHECK (supplyID BETWEEN 301 and 450),
   supplier CHAR(50)
   )
CREATE TABLE SUPPLY4 (
   supplyID INT PRIMARY KEY CHECK (supplyID BETWEEN 451 and 600),
   supplier CHAR(50)
   )
INSERT SUPPLY1 VALUES ('1', 'CaliforniaCorp')
INSERT SUPPLY1 VALUES ('5', 'BraziliaLtd')
INSERT SUPPLY2 VALUES ('231', 'FarEast')
INSERT SUPPLY2 VALUES ('280', 'NZ')
INSERT SUPPLY3 VALUES ('321', 'EuroGroup')
INSERT SUPPLY3 VALUES ('442', 'UKArchip')
INSERT SUPPLY4 VALUES ('475', 'India')
INSERT SUPPLY4 VALUES ('521', 'Afrique')

--create the view that combines all supplier tables
CREATE VIEW all_supplier_view
AS
SELECT *
FROM SUPPLY1
   UNION ALL
SELECT *
FROM SUPPLY2
   UNION ALL
SELECT *
FROM SUPPLY3
   UNION ALL
SELECT *
FROM SUPPLY4

请参见

ALTER TABLE

ALTER VIEW

DELETE

DROP VIEW

INSERT

设计存储过程

sp_depends

sp_help

sp_helptext

sp_rename

系统表

UPDATE

使用标识符

使用分区视图