【问题标题】:Not Able to Sorting in Dynamic SQL无法在动态 SQL 中排序
【发布时间】:2020-11-11 23:26:00
【问题描述】:

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

消息 156,第 15 级,状态 1,第 62 行
关键字“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 很陌生。还是有更好的方法来做到这一点?如果有,请告诉我。

【问题讨论】:

  • 你的代码明显是SQL Server,所以我加了标签。当您询问有关 SQL 的问题时,请为您正在使用的数据库添加标签。
  • 感谢@GordonLinoff 的帮助。
  • 这是动态 SQL。调试动态 SQL 的第一步是打印并检查它。不要期望制作大量动态 SQL 代码并让它第一次运行
  • 这对 SQL 注入来说是危险的!将 2GB 的字符注入动态语句是灾难的根源!
  • 你也在给你注入参数,让这更糟。这是一场等待发生的安全噩梦。您需要摆脱所有不安全的注入。

标签: sql sql-server dynamic-sql


【解决方案1】:

一些改进。

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)并检查它是否包含有效的列名(请参阅下面的两篇“保护自己”文章)。

一些可能有用的文章:

【讨论】:

  • 谢谢你,我会记住这些点并应用,谢谢你的帮助。
【解决方案2】:

思考

    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 

【讨论】:

  • 那一行给order by CASE WHEN ASC = ASC THEN rn ELSE -rn END
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
相关资源
最近更新 更多