SQL Server的以前版本在跟蹤物件相依性方面做的並不好。原因是所有的物件相依性都是由對象ID來跟蹤的,這意味著對象一開始就必須存在。但是,通過根據對象名稱來跟蹤對象SQL Server 2008極大地擴充了跟蹤對象的能力,而不用再依賴ID。該方法的好處是在一些對象已經從資料庫中轉移出去後,還可以繼續跟蹤對象,甚至在對象沒有建立時也可以進行跟蹤。
新管理對象
SQL Server 2008引進了兩個新動態管理函數和新系統檢視表,用於跟蹤物件相依性。這兩個新對象包括Database Engine儲存的有關相關性的資訊,這些相關性是在建立、更改和放棄對象時建立的。在一個對象以名稱的形式出現於儲存在另一個對象中的SQL運算式中時,一個相關性就會在兩個對象之間建立。在運算式中出現的對象稱為被引用實體,而包含SQL運算式的對象稱為引用實體。
sys.sql_expression_dependencies
本視圖含有當前資料庫中使用者定義的一個對象的每個相關性的一個記錄。這些使用者定義物件可以是儲存在當前資料庫中的對象,或者儲存在不同資料庫中並利用部分命名規則(databasename.schemaname.objectname)被引用的對象,在不同的伺服器上並使用四部分命名規則(servername.databasename.schemaname.objectname)通過連結的伺服器被引用的對象,以及在特定對象建立時不存在的對象(稱為延遲物件)。
sys.dm_sql_referenced_entities
使用者在定義特定引用實體時,本函數為通過名稱引用的每個使用者定義物件返回一個行,例如,如果視圖vw_SampleView參考資料表Table1 的Field1、 Field2和 Field3,則將返回四行,針對被引用欄位返回三行,針對錶引用返回一行。
sys.dm_sql_referencing_entities
該函數為使用者在當前資料庫中定義的每個對象返回一個記錄,這些對象通過名稱引用另一個使用者定義物件。例如,如果視圖vw_SampleView引用Table1 和 Table2,則該函數返回兩個記錄,針對每個表引用返回一個記錄。
舉例
以下樣本顯示了如何通過建立一些對象和查詢新DMV在資料庫內部跟蹤相關性。利用下邊的指令碼建立名稱為SalesHistory的表:
CREATE TABLE [dbo].[SalesHistory](
[SaleID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
[Product] [char](150) NULL,
[SaleDate] [datetime] NULL,
[SalePrice] [money] NULL
)
在下邊的指令碼中,建立了名稱為dbo.usp_GetSales的儲存的過程,該過程引用在以上指令碼中建立的SalesHistory表:CREATE PROCEDURE dbo.usp_GetSales
(
@Product VARCHAR(10)
)
AS
BEGIN
SELECT COUNT(SaleID) AS SalesCount, SUM(SalePrice) AS SalesAmount
FROM dbo.SalesHistory sh
END
下邊的指令碼使用表值函型數sys.dm_sql_referenced_returns尋找所有引用SalesHistory表的對象。這一查詢不但返回SalesHistory表的引用,還包含被引用的SalesHistory表中的欄位。值得注意的是CROSS APPLY操作符的使用,這是因為實體是表值型函數,而且在將欄位值賦予表值型函數時需要APPLY操作符。還要注意,如果遇到引用一個不存在的實體欄位, 對sys.dm_referenced_entities函數的調用會出錯: SELECT ReferencedEntityName = o.name, g.referenced_entity_name, referenced_minor_name
FROM sys.objects o
JOIN sys.schemas s on o.schema_id = s.schema_id
CROSS APPLY sys.dm_sql_referenced_entities(s.name + '.' + o.name, 'OBJECT') g
WHERE referenced_entity_name = 'SalesHistory'
在下邊的指令碼中,建立了一個新的名稱為usp_GetSalesFromArchive的儲存的過程,該過程引用不存在的SalesHistoryArchive 表
CREATE PROCEDURE usp_GetSalesFromArchive
(
@Product VARCHAR(10)
)
AS
BEGIN
SELECT COUNT(SaleArchiveID) AS SalesCount, SUM(SaleArchivePrice) AS SalesAmount
FROM dbo.SalesHistoryArchive sh
END
現在可以利用 sys.sql_expression_dependencies系統檢視表尋找引用SalesHistoryArchive 表的任何對象。
或者,可以稍微改變該查詢來尋找儲存的過程usp_GetSalesFromArchive引用的表.
SELECT ReferencingObject = o.name ,
ReferencedObject = d.referenced_entity_name
FROM sys.sql_expression_dependencies d
join sys.objects o on d.referencing_id = o.object_id
WHERE o.name = 'usp_GetSalesFromArchive'
結論
通過對象名稱而不是對象ID跟蹤相關性擁有諸多好處。使用者可能喜歡尋找儲存的過程,該過程引用並不存在的對象,因為這協助使用者尋找不再使用或需要更新的任何儲存的過程。