視圖的創建及使用(sql server 2005)

創建一個虛擬表,該表以一種備用方式提供一個或多個表中的數據。CREATE VIEW 必須是查詢批處理中的第一條語句。

 Transact-SQL 語法約定

語法
 
CREATE VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ]
[ WITH <view_attribute> [ ,...n ] ]
AS select_statement [ ; ]
[ WITH CHECK OPTION ]

<view_attribute> ::=
{
    [ ENCRYPTION ]
    [ SCHEMABINDING ]
    [ VIEW_METADATA ]     } 
 

備註
只能在當前數據庫中創建視圖。視圖最多可以包含 1,024 列。

通過視圖進行查詢時,數據庫引擎 將進行檢查以確保語句中任何位置被引用所有數據庫對象都存在,這些對象在語句的上下文中有效,以及數據修改語句沒有違反任何數據完整性規則。如果檢查失敗,將返回錯誤消息。如果檢查成功,則將操作轉換爲對基礎表的操作。

如果某個視圖依賴於已刪除的表(或視圖),則當有人試圖使用該視圖時,數據庫引擎 將產生錯誤消息。如果創建了新表或視圖(該表的結構與以前的基表沒有不同之處)以替換刪除的表或視圖,則視圖將再次可用。如果新表或視圖的結構發生更改,則必須刪除並重新創建該視圖。

創建視圖時,與視圖有關的信息將存儲在下列目錄視圖中:sys.views、sys.columns 和 sys.sql_dependencies。CREATE VIEW 語句的文本將存儲在 sys.sql_modules 目錄視圖中。

對通過 numeric 或 float 表達式定義的視圖使用索引所得到的查詢結果,可能不同於不對視圖使用索引的類似查詢所得到的結果。這種差異可能是由對基礎表進行 INSERT、DELETE 或 UPDATE 操作時的舍入錯誤引起的。

創建視圖時,數據庫引擎 將保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的設置。使用視圖時,將使用這些原始設置來分析視圖。因此,訪問視圖時,SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的任何客戶端會話設置都不會影響視圖定義。

注意: 
兼容級別設置確定數據庫引擎 是將空字符串解釋爲單個空格還是真正的空字符串。如果兼容級別小於或等於 65,則數據庫引擎 將空字符串解釋爲單個空格。如果兼容級別等於或大於 70,則數據庫引擎 將空字符串解釋爲空字符串。有關詳細信息,請參閱 sp_dbcmptlevel (Transact-SQL)。 
 


可更新視圖
只要滿足下列條件,即可通過視圖修改基礎基表的數據:

任何修改(包括 UPDATE、INSERT 和 DELETE 語句)都只能引用一個基表的列。


視圖中被修改的列必須直接引用表列中的基礎數據。不能通過任何其他方式對這些列進行派生,如通過以下方式:


聚合函數:AVG、COUNT、SUM、MIN、MAX、GROUPING、STDEV、STDEVP、VAR 和 VARP。


計算。不能從使用其他列的表達式中計算該列。使用集合運算符 UNION、UNION ALL、CROSSJOIN、EXCEPT 和 INTERSECT 形成的列將計入計算結果,且不可更新。


被修改的列不受 GROUP BY、HAVING 或 DISTINCT 子句的影響。


上述限制適用於視圖的 FROM 子句中的任何子查詢,就像其應用於視圖本身一樣。通常情況下,數據庫引擎 必須能夠明確跟蹤從視圖定義到一個基表的修改。有關詳細信息,請參閱通過視圖修改數據。

如果上述限制妨礙直接通過視圖修改數據,則可以考慮以下選項:

INSTEAD OF 觸發器

可以對視圖創建 INSTEAD OF 觸發器,以使視圖可更新。將執行 INSTEAD OF 觸發器,而不是執行對其定義了觸發器的數據修改語句。此觸發器允許用戶指定必須發生以處理數據修改語句的操作集合。因此,如果存在給定的數據修改語句(INSERT、UPDATE 或 DELETE)的視圖的 INSTEAD OF 觸發器,則可通過該語句更新相應的視圖。有關 INSTEAD OF 觸發器的詳細信息,請參閱設計 INSTEAD OF 觸發器。


分區視圖

如果視圖爲分區視圖,則可遵循某些限制對其進行更新。必要時,數據庫引擎 將本地分區視圖辨別爲所有參與表和視圖都在同一 SQL Server 實例上的視圖,而將分佈式分區視圖辨別爲視圖中至少有一個表駐留在其他或遠程服務器上的視圖。

有關分區視圖的詳細信息,請參閱創建分區視圖。


分區視圖
分區視圖是通過對成員表使用 UNION ALL 所定義的視圖,這些成員表的結構相同,但作爲多個表分別存儲在同一個 SQL Server 實例中,或存儲在稱爲聯合數據庫服務器的自主 SQL Server 服務器實例組中。

注意: 
在一個服務器上的表上建立的分區視圖包含在 Microsoft SQL Server 2005 中(這樣只是爲了維護向後兼容性),並位於不推薦使用的進程中。對數據進行本地分區的首選方法是通過分區表。有關詳細信息,請參閱 已分區表和已分區索引。
 


在設計分區方案時,必須明確每個分區上包含的數據。例如,Customers 表的數據分佈在三個服務器位置的三個成員表中:Server1 上的 Customers_33、Server2 上的 Customers_66 和 Server3 上的 Customers_99。

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
 

創建分區視圖的條件
選擇 list


應在視圖定義的列列表中選擇成員表中的所有列。


每個 select list 中的同一序號位置上的列應屬於同一類型,包括排序規則。列僅僅屬於可隱式轉換的類型(如通常情況下的 UNION)是不夠的。

此外,至少有一列(例如 <col>)必須按照相同的序號位置顯示在所有選擇列表中。此 <col> 應按照以下方式定義:成員表 T1, ..., Tn 分別在 <col> 上定義了 CHECK 約束 C1, ..., Cn。

在表 T1 上定義的約束 C1 必須是以下格式:

 複製代碼
C1 ::= < simple_interval > [ OR < simple_interval > OR ...]
< simple_interval > :: =
< col > { < | > | <= | >= | = < value >}
| < col > BETWEEN < value1 > AND < value2 >
| < col > IN ( value_list )
| < col > { > | >= } < value1 > AND
< col > { < | <= } < value2 >
 

約束應按照以下方式定義:<col> 的任何指定值最多隻能滿足一個 C1, ..., Cn 約束,從而使約束形成一組不聯接或不重疊的間隔。定義不聯接的約束的列 <col> 稱爲分區列。請注意,分區列在基礎表中可能有不同的名稱。約束應處於啓用和信任狀態,以使它們滿足分區列的上述條件。如果約束被禁用,則使用 ALTER TABLE 的 CHECK CONSTRAINT constraint_name 選項重新啓用約束檢查,並使用 WITH CHECK 選項對其進行驗證。

以下示例顯示有效的約束集合:

 複製代碼
{ [col < 10], [col between 11 and 20] , [col > 20] }
{ [col between 11 and 20], [col between 21 and 30], [col between 31 and 100] }
 

在選擇列表中不能多次使用同一列。


分區列


分區列是表的 PRIMARY KEY 的一部分。


分區列不能是計算列、標識列、默認列或 timestamp 列。


如果成員表中的同一列上存在多個約束,則數據庫引擎將忽略所有約束,且在確定視圖是否爲分區視圖時不考慮這些約束。若要滿足分區視圖的條件,在分區列上應只有一個分區約束。


分區列的可更新性沒有限制。


成員表或基礎表 T1, ..., Tn


表可以是本地表,也可以是通過由四部分組成的名稱或基於 OPENDATASOURCE 或 OPENROWSET 的名稱引用的運行 SQL Server 的其他計算機中的表。OPENDATASOURCE 和 OPENROWSET 語法可以指定表名,但不能指定直接傳遞查詢。有關詳細信息,請參閱 OPENDATASOURCE (Transact-SQL) 和 OPENROWSET (Transact-SQL)。

如果一個或多個成員表是遠程表,則視圖將被稱爲“分佈式分區視圖”,並且將應用附加條件。本部分後面將對其進行說明。


在用 UNION ALL 語句組合的表集合中,同一個表不能出現兩次。


成員表不能對錶中的計算列創建索引。


成員表在編號相同的列上應具有所有 PRIMARY KEY 約束。


視圖中的所有成員表都應具有相同的 ANSI 填充設置。這可以使用 sp_configure 中的 user options 選項或 SET 語句進行設置。


修改分區視圖的條件
只有 Microsoft SQL Server 2005 Developer Edition 允許對分區視圖執行 INSERT、UPDATE 和 DELETE 操作。下列限制應用於修改分區視圖的語句:

即使基礎成員表對這些列具有 DEFAULT 約束或允許 NULL 值,INSERT 語句也必須爲視圖中的所有列提供值。對於那些具有 DEFAULT 定義的成員表列,這些語句無法顯式地使用關鍵字 DEFAULT。


插入到分區列中的值應至少滿足一個基礎約束;否則,插入操作將因違反約束而失敗。


即使列中包含在相應成員表中定義的 DEFAULT 值,UPDATE 語句也不能指定 DEFAULT 關鍵字作爲 SET 子句中的值。


如果成員表包含 text、ntext 或 image 列,則 PRIMARY KEY 列無法通過 UPDATE 語句進行修改。


不能通過 INSERT 或 UPDATE 語句修改視圖中作爲一個或多個成員表中的標識列的列。


如果其中的一個成員表包含 timestamp 列,則不能通過 INSERT 或 UPDATE 語句修改視圖。


如果一個成員表包含觸發器或 ON UPDATE CASCADE/SET NULL/SET DEFAULT 或 ON DELETE CASCADE/SET NULL/SET DEFAULT 約束,則不能修改視圖。


如果語句中存在與相同視圖或任何成員表的自聯接,則不允許對分區視圖使用 INSERT、UPDATE 和 DELETE 操作。

注意: 
若要更新分區視圖,用戶必須具有對成員表的 INSERT、UPDATE 和 DELETE 權限。
 


分佈式分區視圖的附加條件
對於分佈式分區視圖(其中有一個或多個成員表爲遠程表),適用下列附加條件:

將啓動分佈式事務以確保更新所影響的所有節點間的原子性。


應將 XACT_ABORT SET 選項設置爲 ON,以使 INSERT、UPDATE 或 DELETE 語句生效。


在分區視圖中引用的遠程表的所有 smallmoney 和 smalldatetime 列都將分別映射爲 money 和 datetime。因此,本地表中相應的列(在選擇列表中的相同序號位置中)應爲 money 和 datetime。


分區視圖中的所有鏈接服務器都不能是環回鏈接服務器。這是一個指向同一個 SQL Server 實例的鏈接服務器。


對於涉及可更新分區視圖和遠程表的 INSERT、UPDATE 和 DELETE 操作,忽略 SET ROWCOUNT 選項的設置。

設置了成員表和分區視圖的定義後,SQL Server 2005 將查詢優化器將生成智能計劃,從而有效利用查詢訪問成員表中的數據。通過使用 CHECK 約束定義,查詢處理器在成員表間映射鍵值的分佈。用戶發出查詢時,查詢處理器將映射與 WHERE 子句中指定的值進行比較,然後生成使成員服務器間的數據傳輸量減到最少的執行計劃。因此,雖然有些成員表可能位於遠程服務器中,但是 SQL Server 2005 將解析分佈式查詢,使得必須傳輸的分佈式數據量減到最少。有關 SQL Server 2005 如何對分區視圖解析查詢的詳細信息,請參閱解析分佈式分區視圖

有關複製的考慮事項
若要對複製所涉及的成員表創建分區視圖,需要考慮下列事項:

如果基礎表涉及到包含更新訂閱的合併複製或事務性複製,則 uniqueidentifier 列也應包含在選擇列表中。

對分區視圖進行的任何 INSERT 操作都必須爲 uniqueidentifier 列提供 NEWID() 值。因爲無法使用 DEFAULT 關鍵字,所以對 uniqueidentifier 列的任何 UPDATE 操作都必須提供 NEWID() 值。


通過視圖進行的更新複製與在兩個不同的數據庫中複製表時相同:表由不同的複製代理進行處理,因此不能保證更新的順序。

 

參數
schema_name

視圖所屬架構的名稱。

view_name

視圖的名稱。視圖名稱必須符合有關標識符的規則。可以選擇是否指定視圖所有者名稱。

column

視圖中的列使用的名稱。僅在下列情況下需要列名:列是從算術表達式、函數或常量派生的;兩個或更多的列可能會具有相同的名稱(通常是由於聯接的原因);視圖中的某個列的指定名稱不同於其派生來源列的名稱。還可以在 SELECT 語句中分配列名。

如果未指定 column,則視圖列將獲得與 SELECT 語句中的列相同的名稱。

注意: 
在視圖的各列中,列名的權限在 CREATE VIEW 或 ALTER VIEW 語句間均適用,與基礎數據源無關。例如,如果在 CREATE VIEW 語句中授予了 SalesOrderID 列上的權限,則 ALTER VIEW 語句可以將 SalesOrderID 列改名(例如改爲 OrderRef),但仍具有與使用 SalesOrderID 的視圖相關聯的權限。
 


AS

指定視圖要執行的操作。

select_statement

定義視圖的 SELECT 語句。該語句可以使用多個表和其他視圖。需要相應的權限才能在已創建視圖的 SELECT 子句引用的對象中選擇。

視圖不必是具體某個表的行和列的簡單子集。可以使用多個表或帶任意複雜性的 SELECT 子句的其他視圖創建視圖。

在索引視圖定義中,SELECT 語句必須是單個表的語句或帶有可選聚合的多表 JOIN。

視圖定義中的 SELECT 子句不能包括下列內容:

COMPUTE 或 COMPUTE BY 子句


ORDER BY 子句,除非在 SELECT 語句的選擇列表中也有一個 TOP 子句。


INTO 關鍵字


OPTION 子句


引用臨時表或表變量。


因爲 select_statement 使用 SELECT 語句,所以按照 FROM 子句的指定,使用 <join_hint> 和 <table_hint> 提示是有效的。有關詳細信息,請參閱 FROM (Transact-SQL) 和 SELECT (Transact-SQL)。

UNION 或 UNION ALL 分隔的函數和多個 SELECT 語句可在 select_statement 中使用。

CHECK OPTION

強制針對視圖執行的所有數據修改語句都必須符合在 select_statement 中設置的條件。通過視圖修改行時,WITH CHECK OPTION 可確保提交修改後,仍可通過視圖看到數據。如果在 select_statement 中的任何位置使用 TOP,則不能指定 CHECK OPTION。

注意: 
即使指定了 CHECK OPTION,也不能依據視圖來驗證任何直接對視圖的基礎表執行的更新。
 


ENCRYPTION

對 sys.syscomments 表中包含 CREATE VIEW 語句文本的條目進行加密。使用 WITH ENCRYPTION 可防止在 SQL Server 複製過程中發佈視圖。

SCHEMABINDING

將視圖綁定到基礎表的架構。如果指定了 SCHEMABINDING,則不能按照將影響視圖定義的方式修改基表或表。必須首先修改或刪除視圖定義本身,才能刪除將要修改的表的依賴關係。使用 SCHEMABINDING 時,select_statement 必須包含所引用的表、視圖或用戶定義函數的兩部分名稱 (schema.object)。所有引用的對象必須在同一個數據庫內。

不能刪除參與了使用 SCHEMABINDING 子句創建的視圖的視圖或表,除非該視圖已被刪除或更改而不再具有架構綁定。否則,Microsoft SQL Server 2005 Database Engine 將引發錯誤。另外,如果對參與具有架構綁定的視圖的表執行 ALTER TABLE 語句,而這些語句又會影響視圖定義,則這些語句將會失敗。

如果視圖包含別名數據類型列,則無法指定 SCHEMABINDING。

VIEW_METADATA

指定爲引用視圖的查詢請求瀏覽模式的元數據時,SQL Server 實例將向 DB-Library、ODBC 和 OLE DB API 返回有關視圖的元數據信息,而不返回基表的元數據信息。瀏覽模式元數據是 SQL Server 實例向這些客戶端 API 返回的附加元數據。如果使用此元數據,客戶端 API 將可以實現可更新客戶端遊標。瀏覽模式的元數據包含結果集中列所屬的基表的相關信息。

對於用 VIEW_METADATA 創建的視圖,瀏覽模式的元數據在說明結果集內視圖中的列時,將返回視圖名,而不返回基表名。

當使用 WITH VIEW_METADATA 創建視圖時,如果該視圖具有 INSTEAD OF INSERT 或 INSTEAD OF UPDATE 觸發器,則視圖的所有列(timestamp 列除外)都是可更新的。有關可更新視圖的詳細信息,請參閱“備註”。

權限
執行 CREATE VIEW 至少需要對數據庫有 CREATE VIEW 權限,還需要對創建視圖的架構有 ALTER 權限。

示例
A. 使用簡單 CREATE VIEW
以下示例使用簡單 SELECT 語句創建視圖。當需要頻繁地查詢列的某種組合時,簡單視圖非常有用。此視圖的數據來自 AdventureWorks 數據庫的 HumanResources.Employee 和 Person.Contact 表。這些數據提供有關 Adventure Works Cycles 的僱員的姓名和僱用日期信息。對於負責跟蹤工作年限的人員,可創建此視圖,但是不能授予此人訪問這些表中的所有數據的權限。

 複製代碼
USE AdventureWorks ;
GO
IF OBJECT_ID ('hiredate_view', 'view') IS NOT NULL
DROP VIEW hiredate_view ;
GO
CREATE VIEW hiredate_view
AS
SELECT c.FirstName, c.LastName, e.EmployeeID, e.HireDate
FROM HumanResources.Employee e JOIN Person.Contact c on e.ContactID = c.ContactID ;
GO
 

B. 使用 WITH ENCRYPTION
以下示例使用 WITH ENCRYPTION 選項,並顯示計算列、重命名列以及多個列。

 複製代碼
USE AdventureWorks ;
GO
IF OBJECT_ID ('PurchaseOrderReject', 'V') IS NOT NULL
DROP VIEW PurchaseOrderReject ;
GO
CREATE VIEW PurchaseOrderReject
WITH ENCRYPTION
AS
SELECT PurchaseOrderID, ReceivedQty, RejectedQty, RejectedQty / ReceivedQty AS RejectRatio
FROM Purchasing.PurchaseOrderDetail
WHERE RejectedQty / ReceivedQty > 0
AND DueDate > '06/30/2001' ;
GO
 

C. 使用 WITH CHECK OPTION
以下示例顯示名爲 SeattleOnly 的視圖,此視圖引用了五個表,並允許進行數據修改,以便僅適用於居住在西雅圖的僱員。

 複製代碼
USE AdventureWorks ;
GO
IF OBJECT_ID ('SeattleOnly', 'V') IS NOT NULL
DROP VIEW SeattleOnly ;
GO
CREATE VIEW SeattleOnly
AS
SELECT c.LastName, c.FirstName, a.City, s.StateProvinceCode
FROM Person.Contact c JOIN HumanResources.Employee e ON c.ContactID = e.ContactID
JOIN HumanResources.EmployeeAddress ea ON e.EmployeeID = ea.EmployeeID
JOIN Person.Address a ON ea.AddressID = a.AddressID
JOIN Person.StateProvince s ON a.StateProvinceID = s.StateProvinceID
WHERE a.City = 'Seattle'
WITH CHECK OPTION ;
GO
 

D. 使用視圖中的內置函數
以下示例顯示包含內置函數的視圖定義。使用函數時,必須爲派生列指定一個列名。

 複製代碼
USE AdventureWorks ;
GO
IF OBJECT_ID ('SalesPersonPerform', 'view') IS NOT NULL
DROP VIEW SalesPersonPerform ;
GO
CREATE VIEW SalesPersonPerform
AS
SELECT TOP 100 SalesPersonID, SUM(TotalDue) AS TotalSales
FROM Sales.SalesOrderHeader
WHERE OrderDate > '12/31/2000'
GROUP BY SalesPersonID
ORDER BY TotalSales DESC ;
GO
 

E. 使用分區數據
以下示例將使用名稱分別爲 SUPPLY1、SUPPLY2、SUPPLY3 和 SUPPLY4 的表。這些表對應於位於四個國家/地區的四個辦事處的供應商表。

 複製代碼
--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)
);
GO
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');
GO
--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;
 

發佈了47 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章