本文目錄列表: 1、sql server查看可編程對象定義的方式對比 2、整合實現所有可編程對象定義的查看功能的存儲dbo.usp_helptext2 3、dbo.helptext2的選擇性測試 4、總結語 5、參考清單列表 本文目錄列表: 1、sql server查看可編程對象定義的方式對比 2、 ...
本文目錄列表: 1、sql server查看可編程對象定義的方式對比 2、整合實現所有可編程對象定義的查看功能的存儲dbo.usp_helptext2 3、dbo.helptext2的選擇性測試 4、總結語 5、參考清單列表 1、sql server查看可編程對象定義的方式對比 上一篇博文重構sql server的sys.helptext存儲中寫了sys.helptext的限制和輸出格式每行自帶char(13)和char(10)這兩個字元。為了將可編程對象定義查詢方式研究透徹,以下表格列出了查詢可編程對象定義的不同方式的卻別和對可編程對象定義查看的支持程度。
對象類型描述 | 對象類型簡寫 | sys.sp_helptext | sys.sql_modules | sys.system_sql_modules | sys.all_sql_modules | object_definition |
CHECK_CONSTRAINT | C | 支持 | 不支持 | 不支持 | 不支持 | 支持 |
DEFAULT_CONSTRAINT(contraint,stand-alone) | D | 支持 | 支持 | 不支持 | 支持 | 支持 |
SQL_SCALAR_FUNCTION | FN | 支持 | 支持 | 支持 | 支持 | 支持 |
SQL_INLINE_TABLE_VALUED_FUNCTION | IF | 支持 | 支持 | 支持 | 支持 | 支持 |
SQL_STORED_PROCEDURE | P | 支持 | 支持 | 支持 | 支持 | 支持 |
RULE(old-style,stand-alone) | R | 支持 | 支持 | 不支持 | 支持 | 支持 |
REPLICATION FILTER PROCEDURE | RF | 支持 | 支持 | 支持 | 支持 | 支持 |
SQL_TABLE_VALUED_FUNCTION | TF | 支持 | 支持 | 支持 | 支持 | 支持 |
SQL_TRIGGER | TR | 支持(除資料庫DDL觸發器和伺服器觸發器外) | 支持(除伺服器觸發器外) | 不支持 | 支持(除伺服器觸發器外) | 支持(除伺服器觸發器外) |
USER_TABLE | U computed_column | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
VIEW | V | 支持 | 支持 | 支持 | 支持 | 支持 |
註意:
1、帶有_modules的是系統提供的目錄視圖類。 2、sys.sql_modules包括所有用戶定義的可編程對象的,當然也不支持計算列和伺服器觸發器的。 3、sys.system_sql_modules不支持系統定義的類型為C、D、R、TR的對象。 4、sys.all_sql_modules就是sys.sql_modules和sys.system_sql_modules這個視圖的並集結果的,當然也不支持系統定義的類型為C、D、R、TR類型的對象。 5、sys.sp_helptext雖然支持以上表格中除資料庫DDL觸發器和伺服器觸發器之外的可編程對象,但是其輸出格式有限制:1、每行最多225雙位元組字元號,這樣有可能造成輸出將一個標識符分割為前後兩行的。 6、object_definition函數支持以上表格中除伺服器除觸發器和計算列外的可以變成對象。 7、sys.sp_helpttext和object_definition有個功能的限制:1、在SSMS客戶端中如果使用字元串類型變數接收返回的而結果,有可能受制於SSMS客戶端針對字元串變數的最大限制(sql server 2012中的最大限制是43679雙位元組字元長度)不能全部輸出到客戶端,這個缺點可以從通過程式編碼實現得到完美體現。 2、整合實現所有可編程對象定義的查看功能的存儲dbo.usp_helptext2 通過以上幾種方式的對比,我們可以看到那個方式都不能將以上表格中列出的對象類型的定義全部都滿足,為瞭解決這個不足,我們將整合這些功能來封裝在一個存儲(其名稱為dbo.usp_helptext2)。需要註意的一點就是伺服器觸發器本來不是某個資料庫中的對象的,伺服器觸發器和資料庫中可編程對象分開更好的理解,也能簡單些的,不過為了查詢的便利性,我們這次封裝的存儲實現伺服器觸發器定義查看。 功能整合的存儲過程T-SQL代碼如下:IF OBJECT_ID(N'[dbo].[usp_helptext2]', 'P') IS NOT NULL BEGIN DROP PROCEDURE [dbo].[usp_helptext2]; END GO --================================== -- 功能: 查看可編程對象定義 -- 說明: 支持用戶定義類型,可以運行於SQL Server 2005+ -- 創建: yyyy-MM-dd hh:mm-hh:mm XXX 創建內容描述 -- 修改: yyyy-MM-dd hh:mm-hh:mm XXX 修改內容描述 --================================== CREATE PROCEDURE [dbo].[usp_helptext2] ( @nvcObjectName AS NVARCHAR(776) -- 對象名稱,可以支持的對象類型為(C、D、FN、IF、P、R、RF、TF、TR、U、V) ,@nvcComputedColumnName AS NVARCHAR(128) = NULL -- 計算列名稱(如果@nvcObjectName的對象類型為U,則該參數表示計算列名稱) ) AS BEGIN SET NOCOUNT ON; SET @nvcObjectName = ISNULL(@nvcObjectName, N''); IF (@nvcObjectName = N'') BEGIN RAISERROR(16902, -1, -1,N'usp_helptext2', N'@nvcObjectName'); RETURN(1); END SET @nvcComputedColumnName = ISNULL(@nvcComputedColumnName, N''); DECLARE @tntRetVal AS TINYINT; SET @tntRetVal = 0; DECLARE @tblObjDef AS TABLE ( [Text] NVARCHAR(1000) NULL ); DECLARE @intObjectID AS INT ,@chaType AS CHAR(2) ,@nvcText AS NVARCHAR(MAX); SELECT @intObjectID = 0 ,@chaType = '' ,@nvcText = N''; SELECT @intObjectID = [object_id] ,@chaType = [type] FROM [sys].[all_objects] WHERE [type] IN ('C', 'D', 'FN', 'IF', 'P', 'R', 'RF', 'TF', 'TR', 'U', 'V') AND [name] = PARSENAME(@nvcObjectName, 1); IF (@nvcComputedColumnName > N'') -- 獲取計算列定義 BEGIN IF (@chaType NOT IN ('S', 'U', 'TF')) BEGIN RAISERROR(15218, -1, -1, @nvcObjectName); RETURN(1); END INSERT INTO @tblObjDef ([Text]) EXEC [sys].[sp_helptext] @objname = @nvcObjectName -- nvarchar(776) ,@columnname = @nvcComputedColumnName -- sysname IF(@@ROWCOUNT = 0) BEGIN SET @tntRetVal = 1; END SELECT @nvcText = ISNULL([Text], N'') FROM @tblObjDef; END ELSE IF (@intObjectID <> 0) -- 獲取除計算列和伺服器觸發器以外的所有對象類型的定義 BEGIN SET @nvcText = OBJECT_DEFINITION(@intObjectID); IF(@@ROWCOUNT = 0) BEGIN SET @tntRetVal = 1; END END ELSE IF (@intObjectID = 0) -- 嘗試獲取伺服器觸發器定義 BEGIN SELECT @nvcText = T1.[definition] FROM [sys].[server_sql_modules] AS T1 INNER JOIN [sys].[server_triggers] AS T2 ON [T1].[object_id] = [T2].[object_id] WHERE T2.[name] = @nvcObjectName; IF(@@ROWCOUNT = 0) BEGIN SET @tntRetVal = 1; END END SELECT @nvcText AS [Text]; RETURN(@tntRetVal); END GO
以上存儲dbo.usp_helptext2可以完全實現以上表格的所有可編程對象定義查看,不論是系統定義的還是用戶定義的,前提是以上表格中的可編程對象類型定義。當然也存在缺點就是可編程對象定義輸出到SSMS客戶端超過最大限制(SQL Server 2012環境中的時43679雙位元組字元長度)就要出現截斷,這個缺點可以通過代碼編程來完美解決這個缺點。 3、dbo.helptext2的選擇性測試
用戶定義檢查約束測試: 用戶定義約束測試: 系統定義存儲測試: 用戶定義計算列測試: 資料庫DDL觸發器測試 伺服器觸發器測試: 其他對象類型的測試不在全部列舉。 4、總結語 在這次的學習和研究,sql server系統自帶的視圖以及存儲過程針對可編程對象的實現很很完善的,不過葉分散在不同的地方,這次整合也就是將分散在不同地方的聚合在一起提供統一入口來處理。如果不想查看計算列和伺服器觸發器的定義以外的所有可編程對象類型的定義,建議使用object_definition函數,該函數幾乎提供了很完善的功能。這次學習也發現資料庫DDL觸發器在sys.object是無法查看到的,需要在sys.triggers或sys.all_objects目錄視圖中查看到,這個也在object_id函數做了限制的。由於伺服器觸發器本身屬於伺服器的,這個sql server團隊本身也是用了系統表sys.sysschobjs、sys.syspalnames 、sys.syspalvalues,雖然sys.all_objects也是用了系統表sys.syscheobjs,但是卻在sys.all_objects中無法查詢到的,也在object_id函數中做了限制,只能在sys.server_triggers查詢到,這從邏輯上進行了分離,也符合伺服器觸發器的歸屬性質。 希望這個整合的查看可編程對象定義的存儲,可以幫助到需要的人。繼續精進,繼續探究sql server。 5、參考清單列表
- https://msdn.microsoft.com/en-us/library/ms176112.aspx
- https://msdn.microsoft.com/en-us/library/ms175081.aspx
- https://msdn.microsoft.com/en-us/library/ms188034.aspx
- https://msdn.microsoft.com/en-us/library/ms184389.aspx
- https://msdn.microsoft.com/en-us/library/ms176090.aspx
- https://msdn.microsoft.com/en-us/library/ms188746.aspx
- https://msdn.microsoft.com/en-us/library/ms176054.aspx
- https://msdn.microsoft.com/en-us/library/ms187794.aspx
-