創(chuàng)建一個(gè)虛擬表,該表以另一種方式表示一個(gè)或多個(gè)表中的數(shù)據(jù)。CREATE VIEW 必須是查詢批處理中的第一條語(yǔ)句。
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
是視圖的名稱。視圖名稱必須符合標(biāo)識(shí)符規(guī)則??梢赃x擇是否指定視圖所有者名稱。
column
是視圖中的列名。只有在下列情況下,才必須命名 CREATE VIEW 中的列:當(dāng)列是從算術(shù)表達(dá)式、函數(shù)或常量派生的,兩個(gè)或更多的列可能會(huì)具有相同的名稱(通常是因?yàn)槁?lián)接),視圖中的某列被賦予了不同于派生來(lái)源列的名稱。還可以在 SELECT 語(yǔ)句中指派列名。
如果未指定 column,則視圖列將獲得與 SELECT 語(yǔ)句中的列相同的名稱。
說(shuō)明 在視圖的各列中,列名的權(quán)限在 CREATE VIEW 或 ALTER VIEW 語(yǔ)句間均適用,與基礎(chǔ)數(shù)據(jù)源無(wú)關(guān)。例如,如果在 CREATE VIEW 語(yǔ)句中授予了 title_id 列上的權(quán)限,則 ALTER VIEW 語(yǔ)句可以將 title_id 列改名(例如改為 qty),但權(quán)限仍與使用 title_id 的視圖上的權(quán)限相同。
n
是表示可以指定多列的占位符。
AS
是視圖要執(zhí)行的操作。
select_statement
是定義視圖的 SELECT 語(yǔ)句。該語(yǔ)句可以使用多個(gè)表或其它視圖。若要從創(chuàng)建視圖的 SELECT 子句所引用的對(duì)象中選擇,必須具有適當(dāng)?shù)臋?quán)限。
視圖不必是具體某個(gè)表的行和列的簡(jiǎn)單子集。可以用具有任意復(fù)雜性的 SELECT 子句,使用多個(gè)表或其它視圖來(lái)創(chuàng)建視圖。
在索引視圖定義中,SELECT 語(yǔ)句必須是單個(gè)表的語(yǔ)句或帶有可選聚合的多表 JOIN。
對(duì)于視圖定義中的 SELECT 子句有幾個(gè)限制。CREATE VIEW 語(yǔ)句不能:
因?yàn)?select_statement 使用 SELECT 語(yǔ)句,所以在 FROM 子句中指定 <join_hint> 和 <table_hint> 提示是有效的。有關(guān)更多信息,請(qǐng)參見 FROM 和 SELECT。
在 select_statement 中可以使用函數(shù)。
select_statement 可使用多個(gè)由 UNION 或 UNION ALL 分隔的 SELECT 語(yǔ)句。
WITH CHECK OPTION
強(qiáng)制視圖上執(zhí)行的所有數(shù)據(jù)修改語(yǔ)句都必須符合由 select_statement 設(shè)置的準(zhǔn)則。通過(guò)視圖修改行時(shí),WITH CHECK OPTION 可確保提交修改后,仍可通過(guò)視圖看到修改的數(shù)據(jù)。
WITH ENCRYPTION
表示 SQL Server 加密包含 CREATE VIEW 語(yǔ)句文本的系統(tǒng)表列。使用 WITH ENCRYPTION 可防止將視圖作為 SQL Server 復(fù)制的一部分發(fā)布。
SCHEMABINDING
將視圖綁定到架構(gòu)上。指定 SCHEMABINDING 時(shí),select_statement 必須包含所引用的表、視圖或用戶定義函數(shù)的兩部分名稱 (owner.object)。
不能除去參與用架構(gòu)綁定子句創(chuàng)建的視圖中的表或視圖,除非該視圖已被除去或更改,不再具有架構(gòu)綁定。否則,SQL Server 會(huì)產(chǎn)生錯(cuò)誤。另外,如果對(duì)參與具有架構(gòu)綁定的視圖的表執(zhí)行 ALTER TABLE 語(yǔ)句,而這些語(yǔ)句又會(huì)影響該架構(gòu)綁定視圖的定義,則這些語(yǔ)句將會(huì)失敗。
VIEW_METADATA
指定為引用視圖的查詢請(qǐng)求瀏覽模式的元數(shù)據(jù)時(shí),SQL Server 將向 DBLIB、ODBC 和 OLE DB API 返回有關(guān)視圖的元數(shù)據(jù)信息,而不是返回基表或表。瀏覽模式的元數(shù)據(jù)是由 SQL Server 向客戶端 DB-LIB、ODBC 和 OLE DB API 返回的附加元數(shù)據(jù),它允許客戶端 API 實(shí)現(xiàn)可更新的客戶端游標(biāo)。瀏覽模式的元數(shù)據(jù)包含有關(guān)結(jié)果集內(nèi)的列所屬的基表信息。
對(duì)于用 VIEW_METADATA 選項(xiàng)創(chuàng)建的視圖,當(dāng)描述結(jié)果集中視圖內(nèi)的列時(shí),瀏覽模式的元數(shù)據(jù)返回與基表名相對(duì)的視圖名。
當(dāng)用 VIEW_METADATA 創(chuàng)建視圖時(shí),如果該視圖具有 INSERT 或 UPDATE INSTEAD OF 觸發(fā)器,則視圖的所有列(timestamp 除外)都是可更新的。請(qǐng)參見本主題后面的"可更新視圖"。
只能在當(dāng)前數(shù)據(jù)庫(kù)中創(chuàng)建視圖。視圖最多可以引用 1,024 列。
通過(guò)視圖進(jìn)行查詢時(shí),Microsoft® SQL Server™ 將檢查以確定語(yǔ)句中任意位置引用的所有數(shù)據(jù)庫(kù)對(duì)象是否都存在,這些對(duì)象在語(yǔ)句的上下文中是否有效,以及數(shù)據(jù)修改語(yǔ)句是否沒(méi)有違反任何數(shù)據(jù)完整性規(guī)則。如果檢查失敗,將返回錯(cuò)誤信息。如果檢查成功,則將操作轉(zhuǎn)換成對(duì)基礎(chǔ)表的操作。
如果某個(gè)視圖依賴于已除去的表(或視圖),則當(dāng)有人試圖使用該視圖時(shí),SQL Server 將產(chǎn)生錯(cuò)誤信息。如果創(chuàng)建了新表或視圖(該表的結(jié)構(gòu)與以前的基表沒(méi)有不同之處)以替換除去的表或視圖,則視圖將再次可用。如果新表或視圖的結(jié)構(gòu)發(fā)生更改,則必須除去并重新創(chuàng)建該視圖。
創(chuàng)建視圖時(shí),視圖的名稱存儲(chǔ)在 sysobjects 表中。有關(guān)視圖中所定義的列的信息添加到 syscolumns 表中,而有關(guān)視圖相關(guān)性的信息添加到 sysdepends 表中。另外,CREATE VIEW 語(yǔ)句的文本添加到 syscomments 表中。這與存儲(chǔ)過(guò)程相似;當(dāng)首次執(zhí)行視圖時(shí),只有其查詢樹存儲(chǔ)在過(guò)程高速緩存中。每次訪問(wèn)視圖時(shí),都重新編譯其執(zhí)行計(jì)劃。
在通過(guò) numeric 或 float 表達(dá)式定義的視圖上使用索引所得到的查詢結(jié)果,可能不同于不在視圖上使用索引的類似查詢所得到的結(jié)果。這種差異可能是由對(duì)基礎(chǔ)表進(jìn)行 INSERT、DELETE 或 UPDATE 操作時(shí)的舍入錯(cuò)誤引起的。
創(chuàng)建視圖時(shí),SQL Server 保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的設(shè)置。使用視圖時(shí),將還原這些最初的設(shè)置。因此,當(dāng)訪問(wèn)視圖時(shí),將忽略 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的所有客戶端會(huì)話設(shè)置。
說(shuō)明 SQL Server 是將空字符串解釋為單個(gè)空格還是真正的空字符串取決于 sp_dbcmptlevel 的設(shè)置。如果兼容級(jí)別小于或等于 65,SQL Server 就將空字符串解釋為單個(gè)空格。如果兼容級(jí)別等于或大于 70,則 SQL Server 就將空字符串解釋為空字符串。有關(guān)更多信息,請(qǐng)參見 sp_dbcmptlevel。
Microsoft SQL Server 2000 以兩種方法增強(qiáng)可更新視圖的類別:
必要時(shí),SQL Server 將"本地分區(qū)視圖"辨別為所有參與表和視圖都在同一 SQL Server 上的視圖,而將"分布式分區(qū)視圖"辨別為視圖中至少有一個(gè)表駐留在不同(遠(yuǎn)程)服務(wù)器上的視圖。
如果視圖沒(méi)有 INSTEAD OF 觸發(fā)器,或者視圖不是分區(qū)視圖,則視圖只有滿足下列條件才可更新:
CREATE VIEW NoTable AS
SELECT GETDATE() AS CurrentDate,
@@LANGUAGE AS CurrentLanguage,
CURRENT_USER AS CurrentUser
INSERT、UPDATE 和 DELETE 語(yǔ)句在可以引用可更新視圖之前,也必須如上述條件指定的那樣滿足某些限制條件。只有當(dāng)視圖可更新,并且所編寫的 UPDATE 或 INSERT 語(yǔ)句只修改視圖的 FROM 子句引用的一個(gè)基表中的數(shù)據(jù)時(shí),UPDATE 和 INSERT 語(yǔ)句才能引用視圖。只有當(dāng)視圖在其 FROM 子句中只引用一個(gè)表時(shí),DELETE 語(yǔ)句才能引用可更新的視圖。
分區(qū)視圖是通過(guò)對(duì)成員表使用 UNION ALL 所定義的視圖,這些成員表的結(jié)構(gòu)相同,但作為多個(gè)表分別存儲(chǔ)在同一個(gè) SQL Server 中,或存儲(chǔ)在稱為聯(lián)合 SQL Server 2000 服務(wù)器的自主 SQL Server 2000 服務(wù)器組中。
例如,如果使 Customers 表數(shù)據(jù)分布在分別位于三個(gè)服務(wù)器上的三個(gè)成員表中(Customers_33 在 Server1 上,Customers_66 在 Server2 上,Customers_99 在 Server3 上),將以下面的方法在 Server1 上定義分區(qū)視圖:
--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
一般情況下,如果視圖為下列格式,則稱其為分區(qū)視圖:
SELECT <select_list1>
FROM T1
UNION ALL
SELECT <select_list2>
FROM T2
UNION ALL
...
SELECT <select_listn>
FROM Tn
分區(qū)視圖的創(chuàng)建條件
另外,at least one 列(例如 <col>)必須以相同的序號(hào)位置出現(xiàn)在所有 SELECT 列表中。應(yīng)這樣定義 <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 < 10], [col between 11 and 20] , [col > 20] }
{ [col between 11 and 20], [col between 21 and 30], [col between 31 and 100] }
如果一個(gè)或多個(gè)成員表是遠(yuǎn)程表,則視圖稱為 distributed partitioned view,并且適用附加條件。本節(jié)稍后將對(duì)其進(jìn)行討論。
修改分區(qū)視圖的條件
只有 SQL Server 2000 開發(fā)版和企業(yè)版允許在分區(qū)視圖中進(jìn)行 INSERT、UPDATE 和 DELETE 操作。若要修改分區(qū)視圖,語(yǔ)句必須滿足下列條件:
說(shuō)明 若要更新分區(qū)視圖,用戶在成員表上必須具有 INSERT、UPDATE 和 DELETE 權(quán)限。
分布式分區(qū)視圖的附加條件
對(duì)于分布式分區(qū)視圖(當(dāng)一個(gè)或多個(gè)成員表為遠(yuǎn)程表時(shí)),適用下列附加條件:
對(duì)于涉及可更新分區(qū)視圖和遠(yuǎn)程表的 INSERT、UPDATE 和 DELETE 操作,忽略 SET ROWCOUNT 選項(xiàng)的設(shè)置。
當(dāng)設(shè)置好成員表和分區(qū)視圖的定義后,Microsoft SQL Server 2000 將生成智能的查詢計(jì)劃以便有效地訪問(wèn)成員表中的數(shù)據(jù)。通過(guò)使用 CHECK 約束定義,查詢處理器在成員間映射鍵值的分布。當(dāng)用戶發(fā)出查詢時(shí),查詢處理器將映射與 WHERE 子句中指定的值進(jìn)行比較,然后生成使成員服務(wù)器間的數(shù)據(jù)傳輸量減到最少的執(zhí)行計(jì)劃。因此,雖然有些成員表可能位于遠(yuǎn)程服務(wù)器中,但是 SQL Server 2000 將解析分布式查詢,使得必須傳輸?shù)姆植际綌?shù)據(jù)量減到最少。有關(guān) SQL Server 2000 如何解析分區(qū)視圖查詢的更多信息,請(qǐng)參見解析分布式分區(qū)視圖。
復(fù)制的考慮事項(xiàng)
為在復(fù)制所包含的成員表上創(chuàng)建分區(qū)視圖,需要考慮下列事項(xiàng):
CREATE VIEW 權(quán)限默認(rèn)授予 db_owner 和 db_ddladmin 固定數(shù)據(jù)庫(kù)角色成員。sysadmin 固定服務(wù)器角色成員和 db_owner 固定數(shù)據(jù)庫(kù)角色成員可以將 CREATE VIEW 權(quán)限轉(zhuǎn)讓給其他用戶。
若要?jiǎng)?chuàng)建視圖,用戶必須具有 CREATE VIEW 權(quán)限,還必須在視圖所引用的表、視圖和表值函數(shù)上具有 SELECT 權(quán)限,在視圖所喚醒調(diào)用的標(biāo)量值函數(shù)上具有 EXECUTE 權(quán)限。
另外,若要?jiǎng)?chuàng)建 WITH SCHEMABINDING 視圖,用戶必須在每個(gè)引用的表、視圖和用戶定義函數(shù)上具有 REFERENCES 權(quán)限。
下例創(chuàng)建具有簡(jiǎn)單 SELECT 語(yǔ)句的視圖。當(dāng)需要頻繁地查詢列的某種組合時(shí),簡(jiǎn)單視圖非常有用。
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
下例使用 WITH ENCRYPTION 選項(xiàng)并顯示計(jì)算列、重命名列以及多列。
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
下面是用來(lái)檢索加密存儲(chǔ)過(guò)程的標(biāo)識(shí)號(hào)和文本的查詢:
USE pubs
GO
SELECT c.id, c.text
FROM syscomments c, sysobjects o
WHERE c.id = o.id and o.name = 'accounts'
GO
下面是結(jié)果集:
說(shuō)明 text 列的輸出顯示在單獨(dú)一行中。執(zhí)行該存儲(chǔ)過(guò)程時(shí),下列信息將與 id 列信息出現(xiàn)在同一行中。
id text
----------- ------------------------------------------------------------
661577395
???????????????????????????????????????????????????????????????????????...
(1 row(s) affected)
下例顯示名為 CAonly 的視圖,該視圖使得只對(duì)加利福尼亞州的作者應(yīng)用數(shù)據(jù)修改。
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
下例顯示包含內(nèi)置函數(shù)的視圖定義。使用函數(shù)時(shí),必須在 CREATE VIEW 語(yǔ)句中為派生列指定列名。
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
下例使用 @@ROWCOUNT 函數(shù)作為視圖定義的一部分。
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
下例使用名為 SUPPLY1、SUPPLY2、SUPPLY3 和 SUPPLY4 的表,這些表對(duì)應(yīng)于位于不同國(guó)家的四個(gè)辦事處的供應(yīng)商表。
相關(guān)文章--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 SUPPLY1UNION ALL
SELECT *
FROM SUPPLY2
UNION ALL
SELECT *
FROM SUPPLY3
UNION ALL
SELECT *
FROM SUPPLY4