搜索查询动态与静态 - SQL Server 2012

时间:2014-03-27 23:29:49

标签: tsql sql-server-2012 sql-injection dynamic-sql

我需要编写一个搜索查询(存储过程),其中输入参数的数量将超过15.用户可以传递单个参数值或参数组合。

什么是最好的方法

  1. 静态方法如下:

    DECLARE @FirstName VARCHAR(50) = 'XYZ' ,
    @LastName VARCHAR(50) = 'ABC' ,
    @MiddleName VARCHAR(50) = '999-9999%'';  Select 1 as Abc where 1 like ''%1'
    SELECT *
    FROM   [Person].[Person]
    WHERE  FirstName LIKE '%' + @FirstName + '%'
        OR LastName LIKE '%' + @LastName + '%'
        OR MiddleName LIKE '%' + @MiddleName + '%'
    
  2. 动态SQL方法如下:

    DECLARE @FirstName VARCHAR(50) = 'XYZ', @LastName VARCHAR(50) = 'ABC', @MiddleName VARCHAR(50) = '999-9999%'
    
    DECLARE @select VARCHAR(5000) = 'Select * from [Person].[Person] '
    DECLARE @WhereClause VARCHAR(5000) = 'Where'
    IF (@FirstName IS NOT NULL OR @FirstName <> '')
        SET @WhereClause = @WhereClause + ' FirstName Like ''%' + @FirstName + '%'''
    
    IF (@LastName IS NOT NULL OR @LastName<> '') 
        IF (@WhereClause <> 'Where')
            SET @WhereClause = @WhereClause + ' OR LastName Like ''%' + @LastName+ '%'''
        ELSE
            SET @WhereClause = @WhereClause + ' LastName Like ''%' + @LastName+ '%'''
    
    IF (@MiddleName IS NOT NULL OR @MiddleName <> '') 
        IF (@WhereClause <> 'Where')
            SET @WhereClause = @WhereClause + ' OR MiddleName Like ''%' + @MiddleName + '%'''
        ELSE
            SET @WhereClause = @WhereClause + ' MiddleNameLike ''%' + @MiddleName + '%'''
    

    exec(@select + @WhereClause)

  3. 现在问题:

    使用方法1,我必须在WHERE子句中包含每个参数。我认为性能会有所下降,即使参数的值未提供,它仍会在相关列中进行搜索。

    使用方法2我认为它可能是SQL注入。 例:  如果案例2中的参数值作为

    传递
    DECLARE @FirstName VARCHAR(50) = 'XYZ', @LastName VARCHAR(50) = 'ABC', @MiddleName VARCHAR(50) = '999-9999%'';  Select 1 as Abc where 1 like ''%1';
    

    生成的SQL查询将执行

    Select * from [Person].[Person] Where FirstName Like '%XYZ%' OR LastName Like '%ABC%' OR MiddleName Like '%999-9999%';  Select 1 as Abc where 1 like '%1%'
    

    这不好。

    那么以最佳性能对此进行编码的最佳方法是什么。

2 个答案:

答案 0 :(得分:1)

我更喜欢方法#1。

  • 更轻松维护#1中的代码。
  • 在大多数情况下,#1比<2> 更快
  • 在引号内处理引号非常令人头疼。 ' OR LastName Like ''%' + @LastName+ '%'''
  • 动态sql更难以调试。可能不是这种情况。
  • 当您的需求发生变化时,您的动态代码会变得更加混乱 混乱。
  • 查询计划不会在#2中缓存。
  • SQL注入,如您所示。

答案 1 :(得分:0)

动态SQL通常会受到性能影响,因为它无法在SQL Server中缓存查询计划。

我个人也更喜欢方法1,但如果它没有完成,那么它可能会非常慢,特别是因为开放式LIKE语句,例如var LIKE“%text%”可能需要花费大量时间来执行。

我的建议是让输入参数的默认值为null,然后按如下方式构造WHERE子句

SELECT *
FROM table t
WHERE t.column1 = ISNULL(@param1, t.column1)
AND t.column2 = ISNULL(@param2, t.column2)

这意味着在未提供参数的实例中,它只返回所有其他匹配结果。

您可能需要为日期范围匹配做一些聪明的事情但是通过使用参数为NULL的最小和最大可能日期/时间来确保所有记录都在范围内。