在我们需要批量删除数据,或者批量修改实体的状态时,为了性能我们会直接写一个存储过程,并将这一批数据的id用“,”分隔传递给一个存储过程,然后在存储过程中拆分这个字符串,然后执行删除或者更新状态操作。以前每次执行这种操作时我都会在存储过程中拆分字符串。现在sql server支持用.net clr的程序集写函数,存储过程等等。

 

现在我们就牛刀小试,做一个clrsql表值函数。该函数的功能就是传入一个用逗号分隔的数字id字符,返回一个只有一列id的表。
第一步:我们需要新建一个类库项目,并添加一个类SplitIDs

用Clr实现的sql表值函数splitIDsusing System;
用Clr实现的sql表值函数splitIDsusing System.Collections.Generic;
用Clr实现的sql表值函数splitIDsusing System.
Text;
用Clr实现的sql表值函数splitIDsusing Microsoft.SqlServer.Server;
用Clr实现的sql表值函数splitIDsusing System.Collections;
用Clr实现的sql表值函数splitIDsusing System.Data.SqlTypes;
用Clr实现的sql表值函数splitIDs
用Clr实现的sql表值函数splitIDs
public class SplitIDs
用Clr实现的sql表值函数splitIDs{
用Clr实现的sql表值函数splitIDs    
[SqlFunction(FillRowMethodName = "FillRow")]
用Clr实现的sql表值函数splitIDs    
public static IEnumerable DoSplit(String strIDs)
用Clr实现的sql表值函数splitIDs    {
用Clr实现的sql表值函数splitIDs        
return strIDs.Split(',');
用Clr实现的sql表值函数splitIDs    }
用Clr实现的sql表值函数splitIDs
用Clr实现的sql表值函数splitIDs    
public static void FillRow(Object obj, out SqlInt64 id)
用Clr实现的sql表值函数splitIDs    {
用Clr实现的sql表值函数splitIDs        
long value = 0;
用Clr实现的sql表值函数splitIDs        
long.TryParse((string)obj, out value);
用Clr实现的sql表值函数splitIDs        id 
= new SqlInt64(value);
用Clr实现的sql表值函数splitIDs    }
用Clr实现的sql表值函数splitIDs}
用Clr实现的sql表值函数splitIDs

2个注意的点
1.     命名空间声明要去掉,我在测试的过程中刚开始有命名空间的声明,总是注册不成功,后来去掉了存储过程的声明,才注册上
2.     方法必须是静态的并且要有SqlFunction特性,表值函数的返回值是IEnurable

第二步:注册程序集到sql server

用Clr实现的sql表值函数splitIDsUSE [DB_Name]
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
if (object_id('SplitIDs'is not null)
用Clr实现的sql表值函数splitIDs
drop function splitIds;
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
IF  EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'SqlServerUtility')
用Clr实现的sql表值函数splitIDs
DROP ASSEMBLY [SqlServerUtility]
用Clr实现的sql表值函数splitIDs
go
用Clr实现的sql表值函数splitIDs
CREATE ASSEMBLY SqlServerUtility 
用Clr实现的sql表值函数splitIDs
FROM 'D:\Program Files\Microsoft SQL Server\90\UserDefinedAssembly\SqlServerUtility.dll' 
用Clr实现的sql表值函数splitIDs
WITH PERMISSION_SET = SAFE
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
CREATE FUNCTION SplitIDs(@ids Nvarchar(max))
用Clr实现的sql表值函数splitIDs
RETURNS TABLE (id bigint)
用Clr实现的sql表值函数splitIDs
AS 
用Clr实现的sql表值函数splitIDsEXTERNAL NAME SqlServerUtility.SplitIDs.DoSplit
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
EXEC sp_configure "clr enabled",1   
用Clr实现的sql表值函数splitIDs
RECONFIGURE
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs

注册过程中需要注意的是上面注册sql中的最后一块,配置在数据库中启用clr enabled属性。否则即使注册上了函数也不能执行。
注册好了,我们来一个小例子,测试一下函数的执行情况:
select * from splitIDs('1,2,9,1000');
select * from splitIDs('333');
select * from splitIDs(NULL);
执行结果一切正常。
-------------t-sql实现分隔------------
当然这个函数还可以用t-sql直接实现,实现代码如下:

用Clr实现的sql表值函数splitIDsUse DB_Name
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
if (object_id('splitIds'is not null)
用Clr实现的sql表值函数splitIDs
drop function splitIds;
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs
CREATE FUNCTION splitIds(
用Clr实现的sql表值函数splitIDs    
@strIds varchar(max
用Clr实现的sql表值函数splitIDs)
用Clr实现的sql表值函数splitIDs
RETURNS @IDs table (id bigint)
用Clr实现的sql表值函数splitIDs
AS
用Clr实现的sql表值函数splitIDs
BEGIN 
用Clr实现的sql表值函数splitIDs    
declare @i int,@j int,@l int,@v bigint;
用Clr实现的sql表值函数splitIDs    
SET @i = 0;
用Clr实现的sql表值函数splitIDs    
SET @j = 0;
用Clr实现的sql表值函数splitIDs    
SET @l = len(@strIds);
用Clr实现的sql表值函数splitIDs    
while (@j < @l)
用Clr实现的sql表值函数splitIDs    
BEGIN
用Clr实现的sql表值函数splitIDs        
SET @j = charindex(',',@strIds,@i+1);
用Clr实现的sql表值函数splitIDs        
IF @j = 0 set @j = @l+1;
用Clr实现的sql表值函数splitIDs        
SET @v = cast(substring(@strIds,@i+1,@j-@i-1as bigint);
用Clr实现的sql表值函数splitIDs        
INSERT INTO @IDs(id)VALUES(@v)
用Clr实现的sql表值函数splitIDs        
SET @i = @j;
用Clr实现的sql表值函数splitIDs    
END
用Clr实现的sql表值函数splitIDs    
RETURN ;
用Clr实现的sql表值函数splitIDs
END
用Clr实现的sql表值函数splitIDs
GO
用Clr实现的sql表值函数splitIDs

最后测试一下用clr实现和sql直接实现的性能差别;我们声明一个很长的字符串变量,然后让clr的splitIDs和t-sql的splitIDs分别做拆分10次,比较他们的耗时

测试脚本 (在测试脚本中使用的函数名字分别是splitIDs_tsql,splitIDs_clr

执行的结果是:
splitIDs_tsql执行时间10060
splitIDs_clr执行时间266

很明显,用clr写的拆分函数要比tsql的拆分函数快大约50倍。

全文结束

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-07-18
  • 2022-01-04
猜你喜欢
  • 2021-11-27
  • 2021-07-04
  • 2021-12-04
  • 2021-07-31
  • 2021-07-09
  • 2021-09-28
  • 2021-11-04
相关资源
相似解决方案