ORDER BY导致操作数类型冲突

时间:2015-08-11 11:46:18

标签: sql sql-server stored-procedures sql-server-2012

我有一个可以正常工作的存储过程,但我希望为它添加排序。这很好用:

ALTER PROCEDURE [dbo].[GetAll]
    @SID NVARCHAR(MAX) = NULL,
    @DID NVARCHAR(MAX) = NULL,
    @KID NVARCHAR(MAX) = NULL,
    @name NVARCHAR(MAX) = NULL,
    @sortExpression NVARCHAR(MAX) = NULL,
    @sortDirection NVARCHAR(MAX) = NULL,
    @DateFrom DATETIME = NULL,
    @DateTo DATETIME = NULL

AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM [dbo].[MyTable]
    WHERE
        [Message] LIKE CASE WHEN @SID IS NULL THEN [Message] ELSE '%sID=' + @SID + '%' END
    AND
        [Message] LIKE CASE WHEN @DID IS NULL THEN [Message] ELSE '%DID=' + @DID + '%' END
    AND
        [Message] LIKE CASE WHEN @KID IS NULL THEN [Message] ELSE '%CID=' + @KID + '%' END
    AND
        [Message] LIKE CASE WHEN @name IS NULL THEN [Message] ELSE '%name=' + @name + '%' END
    AND
        [Timestamp] BETWEEN ISNULL(@DateFrom, [Timestamp]) AND ISNULL(@DateTo, [Timestamp])
    AND
        [SID] = ISNULL(@SID, [SID])
    AND
        [CID] = ISNULL(@KID, [CID])
END

然后我尝试添加这样的排序:

ALTER PROCEDURE [dbo].[GetAll]
    @SID NVARCHAR(MAX) = NULL,
    @DID NVARCHAR(MAX) = NULL,
    @KID NVARCHAR(MAX) = NULL,
    @name NVARCHAR(MAX) = NULL,
    @sortExpression NVARCHAR(MAX) = NULL,
    @sortDirection NVARCHAR(MAX) = NULL,
    @DateFrom DATETIME = NULL,
    @DateTo DATETIME = NULL

AS
BEGIN
    SET NOCOUNT ON;

    SELECT * FROM [dbo].[MyTable]   -- This is line 24
    WHERE
        [Message] LIKE CASE WHEN @SID IS NULL THEN [Message] ELSE '%sID=' + @SID + '%' END
    AND
        [Message] LIKE CASE WHEN @DID IS NULL THEN [Message] ELSE '%DID=' + @DID + '%' END
    AND
        [Message] LIKE CASE WHEN @KID IS NULL THEN [Message] ELSE '%CID=' + @KID + '%' END
    AND
        [Message] LIKE CASE WHEN @name IS NULL THEN [Message] ELSE '%name=' + @name + '%' END
    AND
        [Timestamp] BETWEEN ISNULL(@DateFrom, [Timestamp]) AND ISNULL(@DateTo, [Timestamp])
    AND
        [SID] = ISNULL(@SID, [SID])
    AND
        [CID] = ISNULL(@KID, [CID])
    ORDER BY
    CASE WHEN @sortDirection = 'asc' THEN
        CASE
            WHEN @sortExpression = 'ID' THEN [ID]
            WHEN @sortExpression = 'Timestamp' THEN [Timestamp]
            WHEN @sortExpression = 'Message' THEN [Message]
            WHEN @sortExpression = 'PID' THEN [PID]
            WHEN @sortExpression = 'CID' THEN [CID]
            WHEN @sortExpression = 'SID' THEN [SID]
            WHEN @sortExpression = 'OType' THEN [OType]
            WHEN @sortExpression = 'OID' THEN [OID]
        END
    END ASC,
    CASE WHEN @sortDirection = 'desc' THEN
        CASE
            WHEN @sortExpression = 'ID' THEN [ID]
            WHEN @sortExpression = 'Timestamp' THEN [Timestamp]
            WHEN @sortExpression = 'Message' THEN [Message]
            WHEN @sortExpression = 'PID' THEN [PID]
            WHEN @sortExpression = 'CID' THEN [CID]
            WHEN @sortExpression = 'SID' THEN [SID]
            WHEN @sortExpression = 'OType' THEN [OType]
            WHEN @sortExpression = 'OID' THEN [OID]
        END
    END DESC
END

这给了我以下错误:

Msg 206, Level 16, State 2, Procedure GetAll, Line 24
Operand type clash: decimal is incompatible with datetime2
Msg 206, Level 16, State 2, Procedure GetAll, Line 24
Operand type clash: ntext is incompatible with datetime2
Msg 206, Level 16, State 2, Procedure GetAll, Line 24
Operand type clash: ntext is incompatible with datetime2
Msg 206, Level 16, State 2, Procedure GetAll, Line 24
Operand type clash: decimal is incompatible with datetime2
Msg 206, Level 16, State 2, Procedure GetAll, Line 24
Operand type clash: uniqueidentifier is incompatible with datetime2

有谁知道这是为什么?我真的不知道我在这里做错了什么。

P.S。我的列和参数命名更合适,但我已经对此帖子进行了审查< 3

1 个答案:

答案 0 :(得分:4)

CASE是一个返回单一类型的表达式。因此,您的类型不兼容。不要试图使它们兼容,而是为每列使用单独的表达式:

(CASE WHEN @sortDirection = 'asc' AND @sortExpression = 'ID' THEN [ID] END) ASC,
(CASE WHEN @sortDirection = 'asc' AND @sortExpression = 'Timestamp' THEN [Timestamp] END) ASC,
. . .
(CASE WHEN @sortDirection = 'desc' AND @sortExpression = 'OID' THEN [OID] END) DESC

非匹配条件都返回NULL,因此它们不会影响排序。

另一种选择是使用动态SQL。