本节主要介绍使用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.附录完整程序
- 使用 系统;
- 使用 System.Data;
- 使用 System.Data.SqlClient;
- 使用 System.Data.SqlTypes;
- 使用 Microsoft.SqlServer.Server;
- 使用 System.Collections;
- 使用 System.Collections.Generic;
- 使用 System.Text;
- 使用 System.Runtime.InteropServices;
- 公共 局部 类 UserDefinedFunctions
- {
- #region标量
- /// <摘要>
- ///标量函数,不带参数
- /// </ summary>
- /// <returns> </ returns>
- [Microsoft.SqlServer.Server.SqlFunction(
- DataAccess = DataAccessKind.Read)]
- 公共静态 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]。[authors]” ,conn);
- 使用 (SqlDataReader dr = com.ExecuteReader(CommandBehavior.CloseConnection))
- {
- 如果 (dr.Read())
- returnValue = dr.GetString(0);
- }
- }
- return returnValue;
- }
- /// <摘要>
- ///标量函数,带参数
- /// </ summary>
- /// <param name =“ par”> </ param>
- /// <returns> </ returns>
- [Microsoft.SqlServer.Server.SqlFunction]
- 公共静态 SqlString UF_Scalar_SayHelloByPar(SqlString par)
- {
- 返回 面值
- }
- #endregion
- #region表格
- /// <摘要>
- ///表值函数。
- /// </ summary>
- /// <returns> </ returns>
- [Microsoft.SqlServer.Server.SqlFunction(
- DataAccess = DataAccessKind.Read,
- FillRowMethodName = “ FillRow_ReturnData” ,
- IsDeterministic = true )]
- 公共静态 IEnumerable UF_Table_GetReturnData()
- {
- List <ReturnData> returnDataList = 新的 List <ReturnData>();
- returnDataList.Add(new ReturnData(“ a” , “ a” ));
- returnDataList.Add(new ReturnData(“ b” , “ b” ));
- returnDataList.Add(new ReturnData(“ c” , “ c” ));
- return returnDataList;
- }
- 公共类 ReturnData
- {
- 公众 的SqlString名为{ 获取; 设置; }
- 公共 SqlString密码{ get ; 设置; }
- public ReturnData(字符串 名称, 字符串 密码)
- {
- 这个.Name =名称;
- 这个.Password =密码;
- }
- }
- 公共静态无效 FillRow_ReturnData(对象returnDataObj ,
- 出 SqlString的名字,
- 出 SqlString密码)
- {
- ReturnData项目= returnDataObj 作为 ReturnData;
- 名称= “” ;
- 密码= “” ;
- 如果 (项目!= null )
- {
- 名称= item.Name;
- 密码= item.Password;
- }
- }
- #endregion
- };
- #region聚合
- [可序列化]
- [StructLayout(LayoutKind.Sequential)]
- [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(
- Format.UserDefined,
- IsInvariantToDuplicates = false ,
- IsInvariantToNulls = true ,
- IsInvariantToOrder = false ,
- MaxByteSize = 8000)]
- 公共类 StringAgg:IBinarySerialize
- {
- 私有 StringBuilder strBuffer;
- 公共无效的 Init()
- {
- strBuffer = new StringBuilder();
- }
- 公共无效 Accumulate(SqlString str)
- {
- strBuffer.Append(字符串.Format(“{0}” ,STR));
- }
- 公共无效 合并(StringAgg组)
- {
- 累积(Group.Terminate());
- }
- 公共 SqlString Terminate()
- {
- return strBuffer.ToString();
- }
- #region IBinary序列化成员
- 公共无效 Read(System.IO.BinaryReader r)
- {
- strBuffer = 新的 StringBuilder(r.ReadString());
- }
- 公共无效 Write(System.IO.BinaryWriter w)
- {
- w.Write(strBuffer.ToString());
- }
- #endregion
- }
- #endregion; 代孕[电13802269370] 北京代孕[电13802269370] 郑州代孕[电13802269370] 深圳代孕[电13802269370]