SQL Server CLR全功略之三--- CLR标量函数,表值函数和聚

本节主要介绍使用CLR创建标量函数,表值函数和聚合函数。

所谓的标量函数指的就是此函数只返回一个值。表值函数返回值是一个表。聚合函数是在select语句中使用的,用来聚合一个结果集,从而Sum()或Count()等内置的函数,而且真正的自定义聚合函数目前只能用CLR来实现。

下面的示例使用了SQLServer自带的pubs数据库。

1.CLR标量函数

1.1无参函数
    /// 
    ///标量函数,不带参数
    /// 
    /// 
    [Microsoft.SqlServer.Server.SqlFunction(
        数据访问= DataAccessKind.Read,
        IsDeterministic =真)] 
    公共静态的SqlString UF_Scalar_SayHello()
    { 
        串returnValue =“ null”; 
        //通过程序在SQL Server内部执行,因此连接字符串写成“ context connection = true”就可以
        使用(SqlConnection conn = new SqlConnection(“ context connection = true”))
        { 
            conn.Open(); 
            SqlCommand com = new SqlCommand(“从[dbo]中选择前1个[au_lname]。[作者]”,conn);
            使用(SqlDataReader dr = com.ExecuteReader(CommandBehavior.CloseConnection))
            { 
                如果(dr.Read())
                    returnValue = dr.GetString(0); //返回au_lname 
            } 
        }

        return returnValue; //返回“ null” 
    }

内部的参数含义为:DataAccess = DataAccessKind.Read表示可访问数据表。关于SqlFunctionAttribute的属性将附录在文章的最后。

    /// 
    ///标量函数,带参数
    /// 
    ///     [ 
    / 
Microsoft.SqlServer.Server.SqlFunction] 
    公共静态SqlString UF_Scalar_SayHelloByPar(SqlString par)
    { 
        return par; 
    }

2.CLR表值函数

表值与标量函数有些不同。因为要返回一个数据集合,所以一定要用一个填充数据的方法,在属性中用FillRowMethodName来表示,并且返回值应该为IEnumerable类型。代码如下:

1.首先自定义返回类型
公共类ReturnData 
    { 
        public SqlString Name {get; 组; 
        公共SqlString密码{get; 组; 
        public ReturnData(字符串名称,字符串密码)
        { 
            this.Name = name; 
            this.Password =密码;
        } 
    }

2.写CLR表值函数
[Microsoft.SqlServer.Server.SqlFunction(
        DataAccess = DataAccessKind.Read,
        FillRowMethodName =“ FillRow_ReturnData”, //这里是此函数的
        特定填充方法IsDeterministic = true)] 
    公共静态IEnumerable UF_Table_GetReturnData()
    { 
        列表returnDataList = new List(); 
        returnDataList.Add(new ReturnData(“ a”,“ a”)); 
        returnDataList.Add(new ReturnData(“ b”,“ b”)); 
        returnDataList.Add(new ReturnData(“ c”,“ c”)); 
        return returnDataList; 
    }

3.写
填充方法public static void FillRow_ReturnData(object returnDataObj,
                       out SqlString name,
                       out SqlString password)
    { 
        ReturnData item = returnDataObj as ReturnData; 
        名称=“”; 
        密码=“”; 
        if(item!= null)
        { 
            name = item.Name; 
            密码= item.Password; 
        } 
    }

这样一个表值函数就写好了。确定有点麻烦,但是表值在某种情况下,也是不可替代的。

3.CLR聚合函数

用户自定义的CLR聚合类中必须四个函数:Init,初始化,累加,合并,终止。的结果返回。
下面的代码显示了字符串的自定义聚合

#地区聚集
[序列化] 
[StructLayout(LayoutKind.Sequential)] 
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
    Format.UserDefined,
    IsInvariantToDuplicates =假,
    IsInvariantToNulls =真,
    IsInvariantToOrder =假,
    MaxByteSize = 8000)] 
公共类StringAgg:IBinarySerialize 

    私有StringBuilder strBuffer;

    公共无效Init()
    { 
        strBuffer = new StringBuilder(); 
    }

    公共无效Accumulate(SqlString str)
    { 
        strBuffer.Append(string.Format(“ {0},”,str)); 
    }

    公共无效合并(StringAgg组)
    { 
        累积(Group.Terminate()); 
    }

    公共SqlString Terminate()
    { 
        return strBuffer.ToString(); 
    }

    #region IBinary序列化成员

    公共无效Read(System.IO.BinaryReader r)
    { 
        strBuffer = new StringBuilder(r.ReadString()); 
    }

    公共无效的Write(System.IO.BinaryWriter w)
    { 
        w.Write(strBuffer.ToString()); 
    }

    #endregion 

#endregion;

4.创建函数的SQL脚本及调用方法
关于CLR Assembly的创建方法前面已经讲过了,这里不再重复

创建函数UF_Scalar_SayHello()
返回nvarchar(32)
作为EXTERNAL NAME CLRDemoAssemly.UserDefinedFunctions.UF_Scalar_SayHello 
进行
创建功能UF_Scalar_SayHelloByPar(@Par为nvarchar(32))
返回为nvarchar(32)
外部NAME CLRDemoAssemly.UserDefinedFunctions.UF_Scalar_SayHelloByPar 

创造功能UF_Table_GetReturnData()
返回表(名称为nvarchar(32),密码为nvarchar(32))
外部NAME CLRDemoAssemly.UserDefinedFunctions .UF_Table_GetReturnData 

创建AGGREGATE StringAgg(@Par nvarchar(32))
返回nvarchar(max)
外部名称CLRDemoAssemly.StringAgg 
转到
选择dbo.UF_Scalar_SayHello()
转到
选择dbo.UF_Scalar_SayHelloByPar('Hello TJVictor')
转到
* *从dbo.UF_Table_GetReturnData()
转到
dbo.StringAgg(au_lauthor)

5.SqlFunctionAttribute的属性

名称 说明
数据访问 指示函数是否需要访问存储在SQL Server的本地实例中的用户数据。
FillRowMethodName 方法的名称,该方法与TVF协定所使用的表值函数(TVF)在同一个类中。
是确定的 指示用户定义的函数是否是确定性的。
精确 指示函数是否涉及不精确的计算,如浮点运算。
名称 函数在SQL Server中注册时所使用的名称。
系统数据访问 指示函数是否需要访问存储在SQL Server的系统目录或虚拟系统表中的数据。
表格定义 如果方法采用表值函数(TVF),则为一个字符串,该字符串表示结果的表定义。
TypeId 当在派生类中实现时,获取该属性的唯一标识符。

6.SqlUserDefinedAggregateAttribute的属性

名称 说明
格式 序列化格式为Format的值之一。如果选择Native,则聚合类一定要被[StructLayout(LayoutKind.Sequential)]修饰;如果选择UserDefined,则聚合类一定要继承IBinarySerialize接口,自己写序列化方法。
IsInvariantToDuplicates 指示聚合是否与重复值无关。
IsInvariantToNulls 指示聚合是否与空值无关。
IsInvariantToOrder 指示聚合是否与顺序无关。
IsNullIfEmpty 指示在没有对任何值进行累积时聚合是否返回空引用。
最大字节大小 聚合实例的最大大小。
名称 聚合的名称。
TypeId 当在派生类中实现时,获取该属性的唯一标识符。

7.附录完整程序

  1. 使用 系统;  
  2. 使用 System.Data;  
  3. 使用 System.Data.SqlClient;  
  4. 使用 System.Data.SqlTypes;  
  5. 使用 Microsoft.SqlServer.Server;  
  6. 使用 System.Collections;  
  7. 使用 System.Collections.Generic;  
  8. 使用 System.Text;  
  9. 使用 System.Runtime.InteropServices;  
  10.   
  11. 公共 局部   UserDefinedFunctions  
  12. {  
  13.     #region标量  
  14.     /// <摘要>  
  15.     ///标量函数,不带参数  
  16.     /// </ summary>  
  17.     /// <returns> </ returns>  
  18.     [Microsoft.SqlServer.Server.SqlFunction(  
  19.         DataAccess = DataAccessKind.Read)]  
  20.     公共静态 SqlString UF_Scalar_SayHello()   
  21.     {  
  22.         字符串 returnValue =  “ null” ;  
  23.         //由于程序是在SQL Server内部执行,所以连接字符串写成“ context connection = true”即可  
  24.         使用 (SqlConnection conn =  new  SqlConnection(“ context connection = true” ))  
  25.         {  
  26.             conn.Open();  
  27.             SqlCommand com =  new  SqlCommand(“从[dbo]中选择前1个[au_lname]。[authors]” ,conn);  
  28.             使用 (SqlDataReader dr = com.ExecuteReader(CommandBehavior.CloseConnection))  
  29.             {  
  30.                 如果 (dr.Read())  
  31.                     returnValue = dr.GetString(0);  
  32.             }  
  33.         }  
  34.   
  35.         return  returnValue;  
  36.     }  
  37.   
  38.     /// <摘要>  
  39.     ///标量函数,带参数  
  40.     /// </ summary>  
  41.     /// <param name =“ par”> </ param>  
  42.     /// <returns> </ returns>  
  43.     [Microsoft.SqlServer.Server.SqlFunction]  
  44.     公共静态 SqlString UF_Scalar_SayHelloByPar(SqlString par)   
  45.     {  
  46.         返回 面值  
  47.     }  
  48.     #endregion  
  49.  
  50.     #region表格  
  51.     /// <摘要>  
  52.     ///表值函数。  
  53.     /// </ summary>  
  54.     /// <returns> </ returns>  
  55.     [Microsoft.SqlServer.Server.SqlFunction(  
  56.         DataAccess = DataAccessKind.Read,  
  57.         FillRowMethodName =  “ FillRow_ReturnData” ,  
  58.         IsDeterministic =  true )]  
  59.     公共静态 IEnumerable UF_Table_GetReturnData()   
  60.     {  
  61.         List <ReturnData> returnDataList =  新的 List <ReturnData>();  
  62.         returnDataList.Add(new  ReturnData(“ a” ,  “ a” ));  
  63.         returnDataList.Add(new  ReturnData(“ b” ,  “ b” ));  
  64.         returnDataList.Add(new  ReturnData(“ c” ,  “ c” ));  
  65.         return  returnDataList;  
  66.     }  
  67.   
  68.     公共 ReturnData   
  69.     {  
  70.         公众 的SqlString名为{  获取设置}  
  71.         公共 SqlString密码{  get 设置}  
  72.         public  ReturnData(字符串 名称,  字符串 密码)  
  73.         {  
  74.             这个.Name =名称;  
  75.             这个.Password =密码;  
  76.         }  
  77.     }  
  78.   
  79.     公共静态无效 FillRow_ReturnData(对象returnDataObj  ,    
  80.                         SqlString的名字,  
  81.                         SqlString密码)  
  82.     {  
  83.         ReturnData项目= returnDataObj  作为 ReturnData;  
  84.         名称=  “” ;  
  85.         密码=  “” ;  
  86.         如果 (项目!=  null )  
  87.         {  
  88.             名称= item.Name;  
  89.             密码= item.Password;  
  90.         }  
  91.     }  
  92.     #endregion  
  93. };  
  94.  
  95. #region聚合  
  96. [可序列化]  
  97. [StructLayout(LayoutKind.Sequential)]  
  98. [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(  
  99.     Format.UserDefined,  
  100.     IsInvariantToDuplicates =  false ,  
  101.     IsInvariantToNulls =  true ,  
  102.     IsInvariantToOrder =  false ,  
  103.     MaxByteSize = 8000)]  
  104. 公共 StringAgg:IBinarySerialize   
  105. {  
  106.     私有 StringBuilder strBuffer;  
  107.   
  108.     公共无效的 Init()   
  109.     {  
  110.         strBuffer =  new  StringBuilder();  
  111.     }  
  112.   
  113.     公共无效 Accumulate(SqlString str)   
  114.     {  
  115.         strBuffer.Append(字符串.Format(“{0}” ,STR));  
  116.     }  
  117.   
  118.     公共无效 合并(StringAgg组)   
  119.     {  
  120.         累积(Group.Terminate());  
  121.     }  
  122.   
  123.     公共 SqlString Terminate()  
  124.     {  
  125.         return  strBuffer.ToString();  
  126.     }  
  127.  
  128.  
  129.     #region IBinary序列化成员  
  130.   
  131.     公共无效 Read(System.IO.BinaryReader r)   
  132.     {  
  133.         strBuffer =  新的 StringBuilder(r.ReadString());  
  134.     }  
  135.   
  136.     公共无效 Write(System.IO.BinaryWriter w)   
  137.     {  
  138.         w.Write(strBuffer.ToString());  
  139.     }  
  140.  
  141.     #endregion  
  142. }  
  143. #endregion;  代孕[电13802269370]  北京代孕[电13802269370]  郑州代孕[电13802269370]  深圳代孕[电13802269370]

猜你喜欢

转载自www.cnblogs.com/bbc2020/p/12484980.html