您需要创建一个 CLR 聚合 UDF。以下是一些示例:
Create CLR function
SQL CLR Binary CLR Aggregate
这是我写的一个涉及按位或运算的示例:
[Serializable]
[Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined,
IsInvariantToDuplicates = false,
IsInvariantToNulls = true,
IsInvariantToOrder = true,
IsNullIfEmpty = true,
MaxByteSize = -1, // -1 represents values above 8000 bytes up to 2 GB.
Name = "udfClrAggVarbinaryBitwiseOR")]
public struct udfClrAggVarbinaryBitwiseOR : IBinarySerialize
{
/// <summary>
/// Deserialize from the reader to recreate the struct
/// </summary>
/// <param name = "r">BinaryReader</param>
public void Read(BinaryReader r)
{
this.Bytes = r.ReadBytes((int)r.BaseStream.Length);
}
/// <summary>
/// Serialize the struct.
/// </summary>
/// <param name = "w">BinaryWriter</param>
public void Write(BinaryWriter w)
{
w.Write(this.Bytes);
}
/// <summary>
/// Used to compute bitwise operations.
/// </summary>
public byte[] Bytes { get; set; }
/// <summary>
/// Used to inform if the accumulation has received values
/// </summary>
public bool HasValue { get; private set; }
public void Init()
{
this.Bytes = new byte[4]; // this was just arbitrarily set for starting values.
this.HasValue = false;
}
public void Accumulate(SqlBinary Value)
{
if (Value.IsNull)
{
// do nothing.
}
else
{
byte[] bytes = (byte[]) Value;
if (!HasValue)
{
// if this is the first value received, take it.
this.Bytes = bytes;
}
else
{
// otherwise, compute the bitwise OR operation.
this.Bytes = bytes.Bin_Or(this.Bytes); // The Bin_Or extension method was defined in the link below.
}
this.HasValue = true;
}
}
public void Merge(udfClrAggVarbinaryBitwiseOR Group)
{
if (Group.HasValue)
{
this.Bytes = Group.Bytes.Bin_Or(this.Bytes);
}
}
public SqlBinary Terminate()
{
// Put your code here
//if (HasValue)
//{
return this.Bytes;
//}
//else
//{
// return System.Data.SqlTypes.SqlBinary.Null;
//}
}
}
我将此处的代码用于 Bin_Or:Binary operations on byte arrays, with parallelism and pointers
实现自定义序列化时,SqlUserDefinedAggregate 属性必须设置为 Format.UserDefined(即不是默认的 Format.Native),并且必须通过实现 IBinarySerialize 手动设置序列化。我在下面提供一个示例。
除非您直接从 Visual Studio 数据库项目正确设置数据库部署,否则部署 CLR 函数可能会很痛苦。 (您需要先安装 SQL Data Tools。)关键是在 Visual Studio 数据库项目中的项目设置 -> 数据库设置 -> 杂项 -> 设置可信任 = true 下正确设置数据库设置。
我正在使用 Visual Studio 2015 和 SQL Server 2014。(我还需要在项目属性 -> SQLCLR -> 目标框架中将我的 .NET 版本设置为 4.5.2,以使其从 VS 2015 部署到 SQL Server 2014。 )
然后,要设置发布,请右键单击您的数据库项目并选择发布数据库。在高级发布设置中,选中“始终重新创建数据库”。 (确保在部署之前备份数据库!!!)为此,您需要一个包含数据的 SQL 脚本,并将其作为部署的一部分。
要生成脚本,在 SQL Server Management Studio 中,右键单击您的数据库并转到任务 -> 生成脚本... ->(脚本整个数据库)-> 下一步 -> 高级 -> 常规 -> 数据类型到脚本 = 仅数据。然后保存到一个新的 sql 脚本文件。
然后将此现有文件添加到您的 Visual Studio 数据库项目中,并在 Visual Studio 的脚本属性中,将生成操作设置为 PostDeploy。这可确保在发布过程中重新创建数据库后加载数据。
要进行调试,您必须启用调试并确保您的防火墙已充分打开。要进行调试,您还需要以管理员身份运行 VS,并在 Visual Studio SQL Server 对象资源管理器中右键单击您的服务器实例,然后选择“允许 SQL/CLR 调试”。每次启动 VS 时都需要这样做。 (这有点烦人,但我还没有找到更好的方法。)
在我提供的示例中,我还需要在 SQLCLR 项目设置中将权限级别设置为 UNSAFE,并且我需要在单独的 C# 项目中添加 Bin_op 函数的类;然后,我编译了该项目(也为 .NET 4.5.2),将该项目添加为对我的数据库项目的引用,并将程序集引用属性标记为 Permission Set = Unsafe。