你的位置:首页 > 数据库

[数据库]sql server查询可编程对象定义的方式对比以及整合


本文目录列表:
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_modulessys.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 NULLBEGIN  DROP PROCEDURE [dbo].[usp_helptext2];ENDGO --==================================-- 功能: 查看可编程对象定义-- 说明: 支持用户定义类型,可以运行于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,则该参数表示计算列名称))ASBEGIN  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);ENDGO 

 


以上存储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

  •