我希望能夠允許指定可選參數,所以我可以過載Accumulate()
方法,可以嗎?T-SQL CLR:您可以使用可選參數創建AGGREGATE嗎?
我想重載允許指定分隔符,我已經看到其他人必須強制指定分隔符,但這種行爲不適合。
CREATE AGGREGATE dbo.Concatenate (@input nvarchar(max), <OPTIONAL PARAMETER HERE>)
RETURNS nvarchar(max)
僅供參考,這裏是包含Accumulate()
方法的聚合類代碼我期待過載:
using System;
using System.Data;
using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.IO;
using System.Text;
namespace CLR.Utilities {
/// <summary>
/// <list type="references">
/// <reference>
/// <name>How to: Create and Run a CLR SQL Server Aggregate</name>
/// <link>http://msdn.microsoft.com/en-us/library/91e6taax(v=vs.90).aspx</link>
/// </reference>
/// <reference>
/// <name>SqlUserDefinedAggregateAttribute</name>
/// <link>http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.server.sqluserdefinedaggregateattribute(v=vs.90).aspx</link>
/// </reference>
/// <reference>
/// <name>Invoking CLR User-Defined Aggregate Functions (Provides seed code for this function)</name>
/// <link>http://technet.microsoft.com/en-us/library/ms131056.aspx</link>
/// </reference>
/// </list>
/// </summary>
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined, //use clr serialization to serialize the intermediate result
IsInvariantToNulls = true, //optimizer property
IsInvariantToDuplicates = false, //optimizer property
IsInvariantToOrder = false, //optimizer property
MaxByteSize = -1) //no maximum size in bytes of persisted value
]
public class Concatenate : IBinarySerialize {
/// <summary>
/// The variable that holds the intermediate result of the concatenation
/// </summary>
private StringBuilder intermediateResult;
/// <summary>
/// Initialize the internal data structures
/// </summary>
public void Init() {
this.intermediateResult = new StringBuilder();
}
/// <summary>
/// Accumulate the next value, not if the value is null
/// </summary>
/// <param name="value"></param>
public void Accumulate([SqlFacet(MaxSize = -1)] SqlString value) {
if (value.IsNull) {
return;
}
this.intermediateResult.Append(value.Value.Trim()).Append(',');
}
/// <summary>
/// Merge the partially computed aggregate with this aggregate.
/// </summary>
/// <param name="other"></param>
public void Merge(Concatenate other) {
this.intermediateResult.Append(other.intermediateResult);
}
/// <summary>
/// Called at the end of aggregation, to return the results of the aggregation.
/// </summary>
/// <returns></returns>
[return: SqlFacet(MaxSize = -1)]
public SqlString Terminate() {
string output = string.Empty;
//delete the trailing comma, if any
if (this.intermediateResult != null
&& this.intermediateResult.Length > 0) {
output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1).Trim();
}
return new SqlString(output);
}
public void Read(BinaryReader r) {
intermediateResult = new StringBuilder(r.ReadString());
}
public void Write(BinaryWriter w) {
w.Write(this.intermediateResult.ToString().Trim());
}
}
}
這裏是我想還修改部署代碼如果可選參數可以設置:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Concatenate]') AND type = N'AF')
DROP AGGREGATE [dbo].[Concatenate]
GO
IF EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'CLR.Utilities' and is_user_defined = 1)
DROP ASSEMBLY [CLR.Utilities]
GO
ALTER DATABASE [DatabaseName] SET TRUSTWORTHY ON
GO
CREATE ASSEMBLY [CLR.Utilities] FROM 'C:\Path\To\File\CLR.Utilities.dll' WITH PERMISSION_SET = UNSAFE
GO
CREATE AGGREGATE [dbo].[Concatenate] (@input nvarchar(max)) RETURNS nvarchar(max)
EXTERNAL NAME [CLR.Utilities].[CLR.Utilities.Concatenate]
GO
GRANT EXECUTE ON [dbo].[Concatenate] TO PUBLIC
GO
據我所知,有沒有辦法讓使用可選參數CLR函數或聚合,這就是可悲 –
「參數」傳遞給聚合方法,而不是Init方法反正。其中存在一個潛在的問題 - 傳遞的參數沒有什麼特別的 - 每行都會得到一個副本。這意味着它們對於每一行都可能不同。那麼,你尊重第一個嗎?或者他們每個人?那麼你如何決定在合併過程中要做什麼? –
@Damien_The_Unbeliever:良好的捕獲,我打算指定Accumulate()方法被重載,然而這很可能不會根據您提供的信息改變任何東西。 –