如何在不使用动态SQL的情况下在存储过程中使用Order By

时间:2011-05-17 05:29:59

标签: sql-server tsql sql-order-by dynamic-sql

我有以下MS SQL存储过程。我需要在不使用动态SQL和sp_executesql方法

的情况下对结果进行排序

@Order by可以包含可能的值ProductName ASCProductName DESCProductCode ASCVendorName DESCVendorCodeClientName

我试图使用ORDER BY CASE,如果ProductNameProductCode属于不同类型,是否有任何问题?

ALTER PROCEDURE [dbo].[SortedReport]
(
    @ClientID INT,
    @RecordLimit,
    @FromDate DATETIME,
    @ToDate DATETIME,
    @OrderBy NVARCHAR(MAX)
)

AS
BEGIN

IF (@OrderBy IS NULL) BEGIN
    SET @OrderBy = 'ProductName';
END    

SELECT TOP (@RecordLimit) 
        sv.ClientID,
        sv.VendorID,
        sv.ProductID,
        sv.TransactionTime,
        sv.ClientName,
        sv.VendorName,
        sv.ProductName,
        sv.ProductCode,
        sv.VendorCode,
FROM SortedReportiew AS sv 
WHERE (sv.ClientID = @ClientID)
    AND (sv.TransactionTime >= @FromDate)
    AND (sv.TransactionTime < @Date)

更新

以下部分是否正确?来自here

的引用
ORDER BY 
    CASE @OrderBy WHEN 'ProductCode ASC' THEN ProductCode WHEN 'ProductCode DESC' THEN ProductCode END DESC,
    CASE @OrderBy WHEN 'ProductName ASC' THEN ProductName WHEN 'ProductName DESC' THEN ProductName END DESC,

2 个答案:

答案 0 :(得分:12)

正如您所说:使用ORDER BY CASE,但多次使用以避免不同列类型的问题:

...
ORDER BY 
 CASE WHEN @OrderBy ='ProductName ASC' THEN sv.ProductName END,
 CASE WHEN @OrderBy ='ProductName DESC' THEN sv.ProductName END DESC,
 CASE WHEN @OrderBy ='ProductCode ASC' THEN sv.ProductCode END,
 CASE WHEN @OrderBy ='ProductCode DESC' THEN sv.ProductCode END DESC,
 CASE WHEN @OrderBy ='VendorName ASC' THEN sv.VendorName END,
 CASE WHEN @OrderBy ='VendorName DESC' THEN sv.VendorName END DESC,
 CASE WHEN @OrderBy ='VendorCode' THEN sv.VendorCode END,
 CASE WHEN @OrderBy ='ClientName' THEN sv.ClientName END

修改

更新了查询以适应您更新的问题。我假设您的意思是ProductCode ASC ProductCode DESC

答案 1 :(得分:3)

据我所知,订购仅使用一列。在这种情况下,我可能会尝试这样的事情:

  1. @OrderBy拆分为@OrderByCol@OrderByDir

  2. 使用此模板:

    ...
    ORDER BY
      CASE @OrderByDir WHEN 'ASC' THEN
        CASE @OrderByCol
          WHEN 'Column1' THEN Column1
          WHEN 'Column2' THEN Column2
          ...
        END
      END ASC,
    
      CASE @OrderByDir WHEN 'DESC' THEN
        CASE @OrderByCol
          WHEN 'Column1' THEN Column1
          WHEN 'Column2' THEN Column2
          ...
        END
      END DESC
    

    或者,如果您使用的是SQL Server 2005+,也许还有这个,作为替代方案:

    WITH sorted AS (
      SELECT
         ... /* columns, omitted */
         Column1Order = ROW_NUMBER() OVER (ORDER BY Column1),
         Column2Order = ROW_NUMBER() OVER (ORDER BY Column2),
         ...
      FROM ...
    )
    SELECT ...
    FROM sorted
    ORDER BY
      CASE @OrderByCol
        WHEN 'Column1' THEN Column1Order
        WHEN 'Column2' THEN Column2Order
        ...
      END * CASE @OrderByDir WHEN 'DESC' THEN -1 ELSE 1 END
    
  3. 正如@Greg Ogle在评论中正确指出的那样,第一个模板只能在各种排序条件属于兼容类型时才能工作,否则语句就会中断。