动态顺序不使用动态sql?

时间:2010-06-15 11:50:42

标签: sql sql-server-2005 dynamic-sql

我有以下存储过程,可以在TemplateName,CreatedOn和UploadedBy上升序和降序排序。运行时的以下SP不会对记录进行排序。如果我用列名替换2,3,4,我收到错误消息“将nvarchar值'测试模板'转换为数据类型int时转换失败。”。请建议如何实现排序

CREATE PROCEDURE [dbo].[usp_SEL_GetRenderingTemplate]
(
  @facilityID INT,
  @sortOrder VARCHAR(5),
  @sortExpression VARCHAR(100),
  @errorCode INT OUTPUT 
)
AS 
BEGIN       
    SET NOCOUNT ON ;
    BEGIN TRY   
        SET @sortOrder = CASE @sortOrder
                           WHEN 'Ascending' THEN 'ASC'
                           WHEN 'Descending' THEN 'DESC'
                           ELSE 'ASC'
                         END
        SELECT  TemplateID,
                TemplateName,
                CreatedOn,
                ( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
        FROM    Templates
                INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
        WHERE   facilityid = @facilityID
        ORDER BY CASE WHEN @sortExpression = 'TemplateName'
                           AND @sortOrder = 'ASC' THEN 2
                      WHEN @sortExpression = 'CreatedOn'
                           AND @sortOrder = 'ASC' THEN 3
                      WHEN @sortExpression = 'UploadedBy'
                           AND @sortOrder = 'ASC' THEN 4
                 END ASC,
                CASE WHEN @sortExpression = 'TemplateName'
                          AND @sortOrder = 'DESC' THEN 2
                     WHEN @sortExpression = 'CreatedOn'
                          AND @sortOrder = 'DESC' THEN 3
                     WHEN @sortExpression = 'UploadedBy'
                          AND @sortOrder = 'DESC' THEN 4
                END DESC
        SET @errorCode = 0


    END TRY
    BEGIN CATCH
        SET @errorCode = -1                            
        DECLARE @errorMsg AS VARCHAR(MAX)  
        DECLARE @utcDate AS DATETIME   
        SET @errorMsg = CAST(ERROR_MESSAGE() AS VARCHAR(MAX))  
        SET @utcDate = CAST(GETUTCDATE() AS DATETIME)  
        EXEC usp_INS_LogException 'usp_SEL_GetFacilityWorkTypeList',
            @errorMsg, @utcDate  
    END CATCH 


END

4 个答案:

答案 0 :(得分:1)

动态排序必须具有相同的数据类型。下面是一个我用来命令三种不同数据类型的例子 - 整数,日期(升序和降序)和字符串。这可能不适合您的情况,但至少您可以看到一些用于转换为通用数据类型的技术。

...

ORDER BY
    Case Parent.RankTypeID
      When 0 Then dbo.Documents.Rank
      When 1 Then Convert(int, dbo.Documents.DateStart, 112)
      When 2 Then (1 - Convert(int, dbo.Documents.DateStart, 112))
      When 3 Then Cast(dbo.Documents.Title as sql_variant)
    End

注意:

112是YYYYMMDD的日期格式 - 对订购有用。

答案 1 :(得分:0)

我们在其中一个产品中执行类似的动态订购。 与您的代码唯一真正不同的是,首先,我们不使用实时联接。 我们创建一个临时表,因此我们可以执行分页,然后应用订单。 我们还使用int来进行排序,减少了字符串比较的开销。

它确实使您的SQL更长一些,但这种方法对于查询优化器来说肯定更快。此外,更重要的是,我不认为你可以在Switch块中混合使用类型进行排序,因此要遵循原始代码,你必须同时转换所有数据,这会使对象失败:(< / p>

所以你有

DECLARE @temp TABLE(ID int identity(1,1), TemplateID int, TemplateName nvarchar(100), CreatedOn datetime, UploadedBy nvarchar(100))
INSERT INTO @temp(TemplateID, TemplateName, CreatedOn, UploadedBy)
SELECT TemplateID,
       TemplateName,
       CreatedOn,
       ( [user].LastName + ' ' + [user].FirstName ) AS UploadedBy
FROM Templates
  INNER JOIN [user] ON [user].UserID = Templates.CreatedBy
WHERE   facilityid = @facilityID

然后:

IF @SortOrder = 1 --'ASC'
  BEGIN
     IF @sort = 2
       Select *
       From @Temp
       Order by TemplateName ASC
     ELSE IF @sort = 3
       Select *
       From @Temp
       Order By CreatedBy ASC
     -- and so on...
  END

ELSE -- descending
  BEGIN
    -- Ad. Inf.
  END

Delete
  From @Temp
  WHERE ID < @pageStart or ID > @pageStart + @pageSize

答案 2 :(得分:0)

  

运行时的以下SP不会   排序记录。如果我用2,3,4替换   列名,

您不应该使用列名替换ORDER BY子句中的2,3,4。当您调用该过程时,只需将要排序的列作为第3个参数进行排序。

EXEC [dbo].[usp_SEL_GetRenderingTemplate] 1,'Ascending','CreatedOn',@vErrorCode

然后,CASE会将查询评估为

...ORDER BY 3 DESC

通过SELECT子句中的第3列(即CreatedOn)对查询进行排序

答案 3 :(得分:0)

问题是在CASE子句中,返回值必须具有相同的数据类型。

您可以使用多个CASE语句http://www.extremeexperts.com/sql/articles/CASEinORDER.aspx

解决此问题

或者将所有内容都转换为相同的数据类型。