了解 SQL 相依性
SQL 相依性是 SQL 運算式中使用的依名稱 (by-name) 參考,可以讓一個實體相依於另一個實體。參考其定義中另一個實體,而且該定義儲存在系統目錄中的實體稱為參考實體。受到另一個實體參考的實體則稱為受參考的實體。由 Database Engine 追蹤的相依性類型有兩種。
結構描述繫結的相依性
結構描述繫結的相依性是兩個實體間的關聯性,只要參考實體存在,就可以防止受參考的實體遭到卸除或修改。使用 WITH SCHEMABINDING 子句建立檢視或使用者自訂函數時,會建立結構描述繫結的相依性。當資料表在 CHECK 或 DEFAULT 條件約束或計算資料行的定義中參考另一個實體 (例如,Transact-SQL 使用者自訂函數、使用者定義型別,或 XML 結構描述集合) 時,也可以建立結構描述繫結的相依性。使用兩段式 (schema_name.object_name) 名稱指定物件不會限定為結構描述繫結的參考。
非結構描述繫結的相依性
非結構描述繫結的相依性是兩個實體間的關聯性,無法防止受參考的實體遭到卸除或修改。
下圖顯示 SQL 相依性的範例。
圖中有兩個實體:程序 X 和程序 Y。程序 X 包含的 SQL 運算式具有程序 Y 的依名稱參考。程序 X 稱為參考實體,而程序 Y 則稱為受參考的實體。由於程序 X 相依於程序 Y,因此如果程序 Y 不存在,程序 X 就會因為執行階段錯誤而失敗。不過,如果程序 X 不存在,程序 Y 並不會失敗。
下列範例顯示預存程序 X 如何相依於預存程序 Y。
USE tempdb;
GO
CREATE PROCEDURE dbo.Y AS
SELECT * FROM sys.objects
GO
CREATE PROCEDURE dbo.X as
EXEC dbo.Y;
GO
若要查看 X 對 Y 的相依性,請執行下列查詢。
SELECT *
FROM sys.sql_expression_dependencies
WHERE referencing_id = OBJECT_ID('X')
AND referenced_id = OBJECT_ID('Y')
AND referenced_schema_name = 'dbo'
AND referenced_entity_name = 'Y'
AND referenced_database_name IS NULL
AND referenced_server_name IS NULL;
GO
參考實體與受參考實體的類型
下表將列出建立並維護相依性資訊的實體類型。該表格會指出是當做參考實體或是受參考的實體追蹤。系統不會針對規則、預設值、暫存資料表、暫存預存程序或系統物件建立或維護相依性資訊。
實體類型 |
參考實體 |
受參考的實體 |
---|---|---|
資料表 |
是* |
是 |
檢視 |
是 |
是 |
Transact-SQL 預存程序** |
是 |
是 |
CLR 預存程序 |
否 |
是 |
Transact-SQL 使用者定義函數 |
是 |
是 |
CLR 使用者定義函數 |
否 |
是 |
CLR 觸發程序 (DML 和 DDL) |
否 |
否 |
Transact-SQL DML 觸發程序 |
是 |
否 |
Transact-SQL 資料庫層級 DDL 觸發程序 |
是 |
否 |
Transact-SQL 伺服器層級 DDL 觸發程序 |
是 |
否 |
擴充預存程序 |
否 |
是 |
佇列 |
否 |
是 |
同義字 |
否 |
是 |
型別 (別名和 CLR 使用者定義型別) |
否 |
是 |
XML 結構描述集合 |
否 |
是 |
資料分割函數 |
否 |
是 |
* 只有當資料表參考計算資料行的定義、CHECK 條件約束或 DEFAULT 條件約束中的 Transact-SQL 模組、使用者定義型別或 XML 結構描述集合時,系統才會將它當做參考實體進行追蹤。
** 所包含之整數值大於 1 的編號預存程序不會當做參考或受參考的實體進行追蹤。
如何追蹤相依性資訊
建立、改變或卸除參考實體時,Database Engine 會自動追蹤相依性資訊,並將該資訊記錄在 SQL Server 系統目錄中。例如,如果您建立參考資料表的觸發程序,就會記錄這些實體之間的相依性。如果之後您卸除該觸發程序,就會從系統目錄移除相依性資訊。
不像舊版 SQL Server 的相依性是依識別碼追蹤,現在的相依性是依名稱追蹤。也就是說,即使受參考的實體在建立參考實體時不存在,Database Engine 還是會追蹤兩個實體之間的相依性資訊。這個情況會因為延遲名稱解析而發生。例如,即使受參考的資料表不存在於資料庫中,也可以成功建立參考資料表的預存程序,但是無法執行該預存程序。Database Engine 會記錄程序和資料表之間的相依性,但是會因為物件不存在而無法記錄資料表的識別碼。如果稍後建立資料表,就會與其他相依性資訊一起傳回該資料表的識別碼。
當受參考的實體依名稱顯示在參考實體的保存 SQL 運算式中時,會追蹤相依性資訊。以下列方式依名稱參考實體時,則會取得相依性資訊:
藉由在 Transact-SQL模組的定義中使用以下任何陳述式:
資料操作語言 (DML) 陳述式 (SELECT、INSERT、UPDATE、DELETE、MERGE)
EXECUTE
DECLARE
SET (搭配使用者自訂函數或使用者定義型別使用 SET 時。例如,DECLARE @var int; SET @var = dbo.udf1)。
使用資料定義語言 (Data Definition Language,DDL) 陳述式 (例如,CREATE、ALTER 或 DROP),在 Transact-SQL 模組定義中參考的實體不會受到追蹤。
藉由當 CREATE、ALTER 或 DROP TABLE 陳述式不在 Transact-SQL 模組中,而且受參考的實體為 Transact-SQL 使用者自訂函數、使用者定義型別,或在計算資料行中定義之 XML 結構描述集合、CHECK 條件約束,或 DEFAULT 條件約束時,使用這些陳述式。
跨資料庫與跨伺服器的相依性
當實體使用有效的三部分名稱參考另一個實體時,會建立跨資料庫相依性。當實體使用有效的四部分名稱參考另一個實體時,則會建立跨伺服器參考。只有在明確指定名稱時,才會記錄伺服器和資料庫的名稱。例如,指定為 MyServer.MyDB.MySchema.MyTable 時,會記錄伺服器和資料庫名稱,但是,指定為 MyServer..MySchema.MyTable 時,則只會記錄伺服器名稱。如需有關有效之多部分名稱的詳細資訊,請參閱<Transact-SQL 語法慣例 (Transact-SQL)>。
適用下列限制:
OPENROWSET、OPENQUERY 以及 OPENDATASOURCE 陳述式的跨伺服器相依性不會受到追蹤。
EXEC (' ') AT linked_server 陳述式的相依性不會受到追蹤。
下表提供受追蹤之跨伺服器和跨資料庫相依性,以及在系統目錄中記錄,並由 sys.sql_expression_dependencies (Transact-SQL) 報告之資訊的摘要。
模組中的 SQL 運算式 |
受到追蹤 |
受參考的伺服器名稱 |
受參考的資料庫名稱 |
受參考的結構描述名稱 |
受參考的實體名稱 |
---|---|---|---|---|---|
SELECT * FROM s1.db2.sales.t1 |
是 |
s1 |
db2 |
sales |
t1 |
SELECT * FROM db3..t1 |
是 |
|
db3 |
|
t1 |
EXEC db2.dbo.Proc1 |
是 |
|
db2 |
dbo |
proc1 |
EXEC (' ') AT linked_srv1 |
否 |
|
|
|
|
EXEC linked_svr1.db2.sales.proc2 |
是 |
linked_svr1 |
db2 |
sales |
proc2 |
相依性追蹤定序的效果
定序可決定排序和比較資料的規則。資料庫的定序用於識別資料庫中的實體相依性資訊。例如,如果預存程序參考使用區分大小寫定序之資料庫中的實體 Some_Table 和 SOME_TABLE,就會因為比較兩個名稱後指出這兩個是不同的實體,而記錄相依性資訊。但是,如果資料庫使用不區分大小寫的定序,只會記錄單一相依性。
若是跨伺服器和跨資料庫的相依性,參考物件所在伺服器的定序用於解析伺服器和資料庫的名稱。目前資料庫的定序則用於解析結構描述名稱和物件名稱。
請考慮下列的預存程序定義。如果在不區分大小寫之伺服器定序的 SQL Server 執行個體上,建立區分大小寫定序之資料庫中的預存程序,會針對實體 srv_referenced.db_referenced.dbo.p_referenced 和 srv_referenced.db_referenced.DBO.P_REFERENCED 記錄兩個相依性。
CREATE PROCEDURE p_referencing AS
EXECUTE srv_referenced.db_referenced.dbo.p_referenced
EXECUTE srv_referenced.db_referenced.DBO.P_REFERENCED
EXECUTE SRV_REFERENCED.DB_REFERENCED.dbo.p_referenced;
解析模稜兩可的參考
當參考可以在執行階段解析成使用者自訂函數、使用者定義型別 (UDT),或 xml 類型資料行的 xquery 參考時,表示該參考模糊不清。
請考慮下列的預存程序定義。
CREATE PROCEDURE dbo.p1 AS
SELECT column_a, Sales.GetOrder() FROM Sales.MySales;
在建立預存程序時,不知道 Sales.GetOrder() 是 Sales 結構描述中,名為 GetOrder 的使用者自訂函數,還是參考名為 Sales、類型是 UDT 而且具有名為 GetOrder() 之方法的資料行。當參考模糊不清時,將 sys.sql_expression_dependencies 和 sys.dm_sql_referenced_entities 中的 is_ambiguous 資料行設定為 1,則可將相依性報告為模糊不清。系統會報告下列相依性資訊:
預存程序及資料表之間的相依性。
預存程序及使用者自訂函數之間的相依性。如果該函數存在,就會報告該函數的識別碼,否則,識別碼為 NULL。
函數的相依性會標示為模糊不清。也就是說,is_ambiguous 是設定為 1。
由於無法繫結資料行所參考的陳述式,因此,不會報告資料行層級相依性。
維護相依性
Database Engine 會同時維護結構描述繫結的相依性與非結構描述繫結的相依性。在影響相依性追蹤的任何作業期間,系統會自動重新整理這些相依性,例如從舊版 SQL Server 升級資料庫,或變更資料庫的定序時。