I read here (and elsewhere) that it's possible, in SQL Server 2008, to build a user-defined aggregate which can return a string longer than 8000 characters. This is exactly what I need.
Supposedly, the method is to set maxByteSize to -1 instead of a number btw 1 and 8000; this should allow any size up to 2GB.
For some reason, apparently, you can't deploy straight from Visual Studio 2008 if you use this setting; so you need to manually deploy.
So: I build my project - GroupConcat (which is supposed to simulate MySQL's group_concat aggregator) - which gives me, in the project's bin folder, a file "SqlClassLibrary.dll". Per the instructions on the above-linked page, I build the assembly in SQL Server. The command executes successfully. However, when I try to actually use the groupconcat aggregator:
select department, dbo.groupconcat(projectNumber) from projectleads group by department
...it says it can't be found. This all works fine if I set maxByteSize to 8000 and deploy directly from within VS2008, but I need >8000. Anybody know what I'm doing wrong?
Thanks -dan
NOTE: I do specifically need to have a groupconcat aggregator function rather than using some of the SQL Server tricks I've often seen.
Alternately, you can use MaxSize property of SqlFacetAttribute to to indicate the varchar size. Note that in the example below I applied this attribute to the SqlString parameters in the Accumulate method and to the return value of the Terminate method. This results in the following SQL signature:
AGGREGATE [dbo].[Concatenate] (@value nvarchar(max), @order int, @seperator nvarchar(max)) RETURNS nvarchar(max)
[Serializable]
[SqlUserDefinedAggregate(
Format.UserDefined,
IsInvariantToOrder = true,
IsInvariantToNulls = true,
IsInvariantToDuplicates = false,
IsNullIfEmpty = false,
MaxByteSize = -1)]
public struct Concatenate : IBinarySerialize
{
public void Init();
public void Accumulate([SqlFacet(MaxSize = -1)] SqlString value,
SqlInt32 order,
[SqlFacet(MaxSize = -1)] SqlString seperator);
public void Merge(Concatenate group);
[return: SqlFacet(MaxSize = -1)]
public SqlString Terminate();
public void Read(BinaryReader r);
public void Write(BinaryWriter w);
}
I don't know if this is any more "correct" than what you ended up doing, but it seems more natural.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With