无法动态排序 SQL

Not Able to Sorting in Dynamic SQL

我想根据传递给 SQL 服务器的 @SortDir 参数对数据进行排序。但是我得到一个错误:

Msg 156, Level 15, State 1, Line 62
Incorrect syntax near the keyword 'ASC'

这是我的动态SQL。我正在对列进行动态搜索,但无法对其进行排序

ALTER PROCEDURE Dsearchsor
    @Name nvarchar(20),
    @Description nvarchar(20),
    @StartIndex int,
    @PageSize int,
    @SortDir nvarchar(20),
    @SortField nvarchar(max)
AS
BEGIN
    DECLARE @SQL nvarchar(max) = N''
    DECLARE @Select nvarchar(max) = N'
    ;With data AS (Select P.Id,
    P.Name,
    P.Description,
    P.Price,
    P.Prorate,
    B.Name as BillingPeriod,
    P.CreatedDate, 
        CASE '+@SortField+'
                WHEN P.Name THEN ROW_NUMBER() OVER (ORDER BY P.Name)
            END rn '

    DECLARE @From NVARCHAR(MAX) = N'From Products P '
    DECLARE @WHERE NVARCHAR(MAX) = N''

    IF @Name IS NOT NULL  
    BEGIN
        SET @WHERE = @WHERE + 'Where P.Name LIKE ''' +'%'+@Name+'%' + ''''
    END

    IF @Description IS NOT NULL
    BEGIN
        IF LEN (@Where) > 0 
        BEGIN
            SET @Where = @Where + ' AND '       
        END

        SET @Where = @Where + 'Description LIKE ''' + +'%'+@Description+'%' + '''' +' )'
    END

    SET @From = @From + ' inner join BillingPeriods B on P.BillingPeriodId = B.Id '
    
    SET @SQL = @Select + @From + @Where +' 
    Select *,(SELECT COUNT(1) FROM data) TotalCount From data                    
    order by CASE WHEN '+ @SortDir +' = ASC' +' THEN rn ELSE -rn END    ******This Line Gives Error******
    OFFSET '+(CAST(@StartIndex as varchar(10)))+' ROWS FETCH NEXT '+(CAST(@PageSize as varchar(10)))+' 
    ROWS ONLY'
     
    EXECUTE sp_executesql @SQL
END

帮我解决这个问题,我对 SQL 还很陌生。或者有更好的方法吗?如果是这样,请告诉我。

想想

    order by CASE WHEN '+ @SortDir +' = ASC' +' THEN rn ELSE -rn END    ******This Line Gives Error******

给予

order by CASE WHEN  = ASC THEN rn ELSE -rn END    

所以你应该转义ASC。可能还有@SortDir

    order by CASE WHEN '''+ @SortDir +''' = ''ASC''' +' THEN rn ELSE -rn END 

一些改进。

SET @SQL = @Select + @From + @Where + N' 
...
order by rn ' + CASE WHEN UPPER(@SortDir) IN (N'ASC', N'DESC') THEN @SortDir 
  ELSE N'DESC' END 
  + N' OFFSET @StartIndex ROWS FETCH NEXT @PageSize ROWS ONLY';

EXEC sys.sp_executesql @SQL, 
  N'@StartIndex int, @PageSize int', 
  @StartIndex, @PageSize;
  • 您的 ORDER BY 不需要运行时 CASE 表达式,事实上,将逻辑放在外面并生成两个不同的查询文本几乎总是更好,这样您就可以获得不同的计划(一个方向可能更有效)。
  • 您还应该确保传递给 @SortDir 的字符串是您期望的字符串。
  • OFFSET / FETCH NEXT 接受参数,所以你应该显式传递这些参数,而不是乱七八糟的字符串连接。
  • 您应该考虑将 @SortField 更改为 nvarchar(128)(没有理由将其更改为 max)并检查它是否包含有效的列名(请参阅两个“保护自己”文章)。

一些可能有用的文章: