Определяемый пользователем агрегат в SQL Server 2008 - как выполнить развертывание с MaxByteSize = -1? - PullRequest
3 голосов
/ 07 марта 2009

Я прочитал здесь (и в других местах), что в SQL Server 2008 возможно создать определяемый пользователем агрегат, который может возвращать строку длиной более 8000 символов. Это именно то, что мне нужно.

Предположительно, метод должен установить maxByteSize в -1 вместо числа между 1 и 8000; это должно разрешить любой размер до 2 ГБ.

По какой-то причине, очевидно, вы не можете развернуть прямо из Visual Studio 2008, если используете этот параметр; поэтому вам нужно вручную развернуть.

Итак: я строю свой проект - GroupConcat (который должен имитировать агрегатор group_concat MySQL) - который дает мне в папке bin проекта файл "SqlClassLibrary.dll". В соответствии с инструкциями на указанной выше странице я собираю сборку в SQL Server. Команда выполняется успешно. Однако когда я пытаюсь на самом деле использовать агрегатор groupconcat:

select department, dbo.groupconcat(projectNumber) from projectleads group by department

... он говорит, что не может быть найден. Это все работает нормально, если я установил maxByteSize на 8000 и развернул его непосредственно из VS2008, но мне нужно> 8000. Кто-нибудь знает, что я делаю не так?

Спасибо -дан

ПРИМЕЧАНИЕ: Мне действительно нужно иметь агрегаторную функцию groupconcat, а не использовать некоторые приемы SQL Server, которые я часто видел.

Ответы [ 2 ]

3 голосов
/ 03 мая 2012

Кроме того, вы можете использовать MaxSize свойство SqlFacetAttribute для указания размера varchar. Обратите внимание, что в приведенном ниже примере я применил этот атрибут к параметрам SqlString в методе Accumulate и к возвращаемому значению метода Terminate. Это приводит к следующей подписи SQL:

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);
}

Я не знаю, является ли это более "правильным", чем то, что вы в итоге сделали, но это кажется более естественным.

1 голос
/ 10 марта 2009

Понял ... После построения решения в Vis Studio, предположив, что я удалил .dll, который он создает, в c: \ temp и назвал его GroupConcat.dll:

CREATE ASSEMBLY GroupConcat from 'C:\temp\GroupConcat.dll' with permission_set = safe
GO

CREATE AGGREGATE groupconcat(@input nvarchar(max))
RETURNS nvarchar(max)
EXTERNAL NAME GroupConcat
GO

Вот так.

...