Не может использоваться в операторе PIVOT, потому что он не инвариантен к NULL - PullRequest
1 голос
/ 19 августа 2011

Я создаю статистическую функцию для строкового столбца в SQL Server 2008.

код C # выглядит следующим образом:

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)]
public struct strconcat : IBinarySerialize
{
    private List<String> values;

    public void Init()
    {
        this.values = new List<String>();
    }

    public void Accumulate(SqlString value = new SqlString())
    {
        this.values.Add(value.Value);
    }

    public void Merge(strconcat value)
    {
        this.values.AddRange(value.values.ToArray());
    }

    public SqlString Terminate()
    {
        return new SqlString(string.Join(", ", this.values.ToArray()));
    }

    public void Read(BinaryReader r)
    {
        int itemCount = r.ReadInt32();
        this.values = new List<String>(itemCount);
        for (int i = 0; i <= itemCount - 1; i++)
        {
            this.values.Add(r.ReadString());
        }
    }

    public void Write(BinaryWriter w)
    {
        w.Write(this.values.Count);

        foreach (string s in this.values)
        {
            w.Write(s);
        }
    }
}

И запрос в SQL:

DECLARE @listCol NVARCHAR(2000)

SELECT  @listCol = STUFF(( SELECT '],[' + A.Name
                        FROM Attribute A,Category C
                        WHERE A.CategoryId = C.Id
                        ORDER BY A.DisplayOrder DESC
                        FOR XML PATH('')), 1, 2, '') + ']'
DECLARE @query NVARCHAR(2000)
SET @query =

N'SELECT * FROM (SELECT P.*,A.Name AttributeName,PA.OriginalValue FROM Product P,Product_Attribute PA, Attribute A WHERE P.Id = PA.ProductId AND A.Id = PA.AttributeId) src
PIVOT 
(
    dbo.strconcat(OriginalValue) FOR AttributeName 
    IN ('+@listCol+')) AS pvt'

EXECUTE (@query)

Но SQL Server возвращает ошибку:

Сообщение 406, Уровень 16, Состояние 1, Строка 5
dbo.strconcat нельзя использовать в операторе PIVOT, поскольку он не инвариантен для значений NULL.

Я гуглил, но не знаю, как это исправить.

Пожалуйста, помогите мне!

1 Ответ

2 голосов
/ 19 августа 2011

Если ваш агрегат инвариантен к нулям, необходимо пометить его как таковой в SqlUserDefinedAggregateAttribute , что-то вроде:

[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000,
   IsInvariantToNulls = true)]

Свойство IsInvariantToNulls описывает требование следующим образом:

Используемое обработчиком запросов, это свойство имеет значение true, если агрегат инвариантен относительно нулей.То есть агрегат S, {NULL} совпадает с агрегатом S. Например, агрегатные функции, такие как MIN и MAX, удовлетворяют этому свойству, а COUNT (*) - нет.

Глядя на ваш агрегат, я думаю, что вам может потребоваться выполнить некоторую работу в вашем методе Add - если переданное значение равно нулю, может быть, не добавлять его в список?

...