网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > 数据库 > 正文

C#实现SQLServer2005的扩展聚合函数

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

今下午没什么事,想将以前费了好大力气写的一个对二维表查询的存储过程进行改进,存储过程用到了好几个游标动态生成SQL,且有两三百行,不但别人很难看懂,自已隔一段时间去看,都得老半天。当初也时没办法,为了实现功能就没考虑这么多了,今就想试试用case when 能不能把游标给去了,使变得更简洁,可读性强,还可提高性能。

  做到一半时遇到一个问题,动态生成case when 拼装成的sql查询出的结果,按instanceID合并成一行的问题,将下图一的结果合并成图二的结果,

各列值的类型是不确定的(表中各列是用户通过系统自定义添加进去),要是数据型好办,用Sum函数。

                             图一 

 图二

  想自定义一个类sum功能的对串进行拼接处理的聚合方法,在网上找了资料,发现可以用C#等语言开发自定义的聚合函数,因为.net是编译中 IL代码,理论上,只要是代码符合CTS,不同语言的代码是能互相调用。

     在vs2008用C#开发聚合函数过程:

首先用VS2008/VS2005建立一个SQL Server项目,如图6所示。

图6

点击“确定”按钮后,SQL Server项目会要求连接一个数据库,我们可以选择一个数据库,如图7所示。

 

图7

然后在工程中加入一个聚合类(joinstr.cs),如图8所示(可以开发Trigger 等)。

图8

joinstr.cs中的最终代码如下:

  1. using System; 
  2. using System.Data; 
  3. using System.Data.SqlClient; 
  4. using System.Data.SqlTypes; 
  5. using Microsoft.SqlServer.Server; 
  6. using System.Text; 
  7.  
  8.  
  9. [Serializable] 
  10. [SqlUserDefinedAggregate( 
  11.     Format.UserDefined, //use custom serialization to serialize the intermediate result 
  12.     IsInvariantToNulls = true//optimizer property 
  13.     IsInvariantToDuplicates = false//optimizer property 
  14.     IsInvariantToOrder = false//optimizer property     
  15.     MaxByteSize = 8000) //maximum size in bytes of persisted value 
  16.  
  17.  
  18. public struct JionStr:IBinarySerialize 
  19.     private StringBuilder sbIntermediate; 
  20.     public void Init() 
  21.     { 
  22.        sbIntermediate = new StringBuilder(); 
  23.     } 
  24.  
  25.     public void Accumulate(SqlString Value) 
  26.     { 
  27.  
  28.         if (Value == null || Value.ToString().ToLower().Equals("null")) 
  29.         { 
  30.             return
  31.         } 
  32.         else 
  33.         { 
  34.             sbIntermediate.Append(Value); 
  35.         } 
  36.     } 
  37.  
  38.     public void Merge(JionStr Group) 
  39.     { 
  40.         sbIntermediate.Append(Group.sbIntermediate); 
  41.     } 
  42.  
  43.     public SqlString Terminate() 
  44.     { 
  45.          
  46.         return new SqlString(sbIntermediate.ToString()); 
  47.     } 
  48.  
  49.     // This is a place-holder member field 
  50.     private int var1; 
  51.  
  52.  
  53.     #region IBinarySerialize Members 
  54.  
  55.     public void Read(System.IO.BinaryReader r) 
  56.     { 
  57.         sbIntermediate = new StringBuilder(r.ReadString()); 
  58.     } 
  59.  
  60.     public void Write(System.IO.BinaryWriter w) 
  61.     { 
  62.         w.Write(this.sbIntermediate.ToString());     
  63.     } 
  64.  
  65.     #endregion 

由于本例需要聚合字符串,而不是已经被序列化的类型,如int等,因此,需要实现 IBinarySerialize接口来手动序列化。使用C#实现SQL Server聚合函数,也会受到字符串最大长度为8000的限制。
在编写完上述代码后,可以使用Visual Studio来部署(右向工程,在弹出菜单上选“部署”即可)。
    也可以使用SQL语句来部署。假设上面的程序生成的dll为AggregateDemo.dll,可以使用下面的SQL语句来部署:

  1. CREATE ASSEMBLY JoinStr FROM 'D:\DotNet\TestDemo\AggregateDemo\bin\Debug\AggregateDemo.dll' 
  2.  
  3. CREATE AGGREGATE JionStr (@input nvarchar(200)) RETURNS nvarchar(max) 
  4. EXTERNAL NAME JoinStr 

要注意的是,字符串类型需要用nvarchar,而不能用varchar。

第一条SQL语句是装载dll,第二条SQL语句是注册joinstr聚合函数(每 一个C#类就是一个聚合函数)
在执行上面的SQL语句之前,需要将SQL Server2005的clr功能打开。(surface Area Configuration for Features)如图9所示。

如果想删除上面建立的聚合函数,可以使用如下的SQL语句:

  1. drop aggregate JoinStr 

在删除聚合函数后,可以将AggregateDemo.dll卸载。

  1. drop assembly JoinStr 

现在可以使用joinstr来聚合字符串了。

  1. SELECT InstanceID, 
  2.       dbo.JionStr(case FieldID when '1' then FieldValue else null endas  
  3.   FROM  tb  
设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师