在SQL Server中使用变量进行分页排序

时间:2011-11-01 15:41:46

标签: sql sql-server-2008

此SQL语句在ORDER BY'+ @SortField +''+ @SortOrder +'部分的SQL Server中被标记。任何想法我该如何解决?

ALTER PROC [sbuser].[sp_MemberMailList ]
@MemberMailID bigint = null,
@FromMemberID bigint = null,
@ToMemberID bigint = null,
@Subject varchar(150) = null,
@Message varchar(8000) = null,
@FromDeletedFlag bit = null,
@ToDeletedFlag bit = null,
@FromArchivedFlag bit = null,
@ToArchivedFlag bit = null,
@ReadFlag bit = null,
@SQL nvarchar(4000) = null,
@SortField varchar(100) = null,
@SortOrder varchar(25) = null,
@NotificationSent bit = null,
@MemberID bigint = null,
@OnHold bit = 0,
@SpecialMail varchar(1) = 'N',
@PageSize float = null,
@PageNum int = 1,
@TotalPages float = null,
@StartDate datetime = null,
@EndDate datetime = null,
@MODE varchar(50)

AS

IF @MODE = 'INBOX-MAIL'
BEGIN
    SELECT @TotalPages = COUNT(*)/@PageSize
    FROM MemberMail a
    INNER JOIN Member b ON b.MemberID = a.FromMemberID
    WHERE a.ToMemberID = @ToMemberID
    AND a.ToDeletedFlag = 0
    AND a.OnHold = 0
    AND a.ToArchivedFlag = 0;

    WITH InMails AS
    (
        SELECT ROW_NUMBER() OVER(ORDER BY ' + @SortField + ' ' + @SortOrder + ') AS RowNum,
        a.MemberMailID,
        a.FromMemberID,
        a.Subject,
        a.CreateDate,
        b.UserName,
        a.ToReadFlag,
        b.Firstname,
        b.Lastname,
        b.MemberDisplayName AS DisplayName
        FROM MemberMail a
        INNER JOIN Member b ON b.MemberID = a.FromMemberID
        WHERE a.ToMemberID = @ToMemberID
        AND a.ToDeletedFlag = 0
        AND a.OnHold = 0
        AND a.ToArchivedFlag = 0
    )
    SELECT * 
    FROM InMails
    WHERE RowNum BETWEEN (@PageNum - 1) * @PageSize + 1 AND @PageNum * @PageSize
    ORDER BY CreateDate DESC
END

任何帮助将不胜感激..

非常感谢

3 个答案:

答案 0 :(得分:1)

SELECT ROW_NUMBER() OVER(ORDER BY ' + @SortField + '   ' + @SortOrder + ') AS RowNum,
                                  ^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^
                                    string #1              string #2

                                                      ^---no operator

除非您的代码示例中没有显示外部字符串,否则您无法像这样构建order by子句。你有两个不同的带引号的字符串,其间有空格。

答案 1 :(得分:1)

您无法使用变量指定字段或排序方向。整个SQL语句需要是一个动态字符串来执行此操作。

所以

SELECT ROW_NUMBER() OVER(
    ORDER BY [field expression] asc|desc) AS RowNum

很好,按原样

exec('SELECT ROW_NUMBER() OVER(' + 
    'ORDER BY ' + @SortField + ' ' + @SortOrder + ') AS RowNum ...')

但是

SELECT ROW_NUMBER() OVER(
    ORDER BY ' + @SortField + ' ' + @SortOrder + ') AS RowNum

SQL中的查询编译器无法处理。

答案 2 :(得分:1)

您似乎正在尝试动态更改字段ORDER BY ROW_NUMBER()排名功能。你无法按照自己的方式去做。

您需要使用动态SQL来完成您正在尝试的内容。您应该阅读The Curse and Blessings of Dynamic SQL以便更好地理解机制以及如何保护自己免受SQL注入。

如果由于某种原因你不想使用动态SQL,你可以生成一个巨大的case语句。例如,下面这个样本取自gbn对Dynamic order direction的回答。

SELECT
     Columns you actually want
FROM
    (
    SELECT
         Columns you actually want,
         ROW_NUMBER() OVER (ORDER BY AddedDate) AS AddedDateSort,
         ROW_NUMBER() OVER (ORDER BY Visible) AS VisibleSort,
         ROW_NUMBER() OVER (ORDER BY AddedBy) AS AddedBySort,
         ROW_NUMBER() OVER (ORDER BY Title) AS TitleSort
    FROM
         myTable
    WHERE
         MyFilters...
    ) foo
ORDER BY
     CASE @OrderByColumn
        WHEN 'AddedDate' THEN AddedDateSort
        WHEN 'Visible' THEN VisibleSort    
        WHEN 'AddedBy' THEN AddedBySort
        WHEN 'Title' THEN TitleSort
     END * @multiplier;

如果你这样做,你应该注意性能问题,因为索引可能不会用于排序。