說明:本文依據網絡轉載整理而成,因為時間關系,其中原理暫時並未深入研究,只是整理備份留個記錄而已。
目標:在SQL Server中自定義聚合函數,在Group BY語句中 ,不是單純的SUM和MAX等運算,可以加入拼接字符串。
環境:
1:Sqlserver 2008 R2
2:Visual Studio 2013
第一部分:
.net代碼:
using System;
using System.Data;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined, //使用UserDefined 序列化格式
IsInvariantToNulls = true, //聚合是否與空值有關
IsInvariantToDuplicates = false, //聚合是否與重復值有關
IsInvariantToOrder = false, //聚合是否與順序有關
MaxByteSize = 8000) //聚合實例的最大大小(以字節為單位)
]
public class Concatenate : IBinarySerialize
{
/// <summary>
/// 定義變量
/// </summary>
private StringBuilder intermediateResult;
/// <summary>
/// 初始化
/// </summary>
public void Init()
{
this.intermediateResult = new StringBuilder();
}
/// <summary>
/// 如果某一個字符不為空,用";"追加
/// </summary>
/// <param name="value"></param>
public void Accumulate(SqlString value,string contChar) //symbol
{
if (value.IsNull)
{
return;
}
this.intermediateResult.Append(value.Value).Append(contChar);
}
/// <summary>
/// 合並字符
/// </summary>
/// <param name="other"></param>
public void Merge(Concatenate other)
{
this.intermediateResult.Append(other.intermediateResult);
}
/// <summary>
/// 處理最后的","
/// </summary>
/// <returns></returns>
public SqlString Terminate()
{
string output = string.Empty;
//刪除最后的","
if (this.intermediateResult != null
&& this.intermediateResult.Length > 0)
{
output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);
}
return new SqlString(output);
}
public void Read(BinaryReader r)
{
intermediateResult = new StringBuilder(r.ReadString());
}
public void Write(BinaryWriter w)
{
w.Write(this.intermediateResult.ToString());
}
}
編譯生成DLL,注意:SqlServer 2008 R2 不支持.Net Framework 4.5 ,所以生成dll的時候選在.net framework 3.5
第二步:啟用數據庫對CLR支持的配置
EXEC sp_configure 'clr enabled', 1 RECONFIGURE WITH OVERRIDE GO
第三步:加載CLR程序集並創建自定義函數
USE Test --選擇數據庫 CREATE ASSEMBLY SQL_Aggregate FROM 'E:\WorkSpace\LetMeTry\WindowsFormsApplication2\SqlCustomFunction\bin\Debug\SqlCustomFunction.dll' --生成的DLL路徑 GO CREATE AGGREGATE SQL_Aggregate (@input nvarchar(200),@contChar nvarchar(1)) RETURNS nvarchar(max) EXTERNAL NAME SQL_Aggregate.Concatenate
第四步:測試
USE Test --創建測試數據 create table tb(ID int,Name varchar(10)) insert into tb select 1,'a' union all select 1,'b' union all select 2,'c' union all select 2,'e' union all select 3,'d' go --自定義聚合函數使用例子(第二個參數為拼接字符串的連接符) select id,dbo.SQL_Aggregate([Name],'+') AS Test from tb group by id
