我需要编写一个搜索查询(存储过程),其中输入参数的数量将超过15.用户可以传递单个参数值或参数组合。
什么是最好的方法
静态方法如下:
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 + '%'
动态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)
现在问题:
使用方法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%'
这不好。
那么以最佳性能对此进行编码的最佳方法是什么。
答案 0 :(得分:1)
我更喜欢方法#1。
' OR LastName Like ''%' + @LastName+
'%'''
答案 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的最小和最大可能日期/时间来确保所有记录都在范围内。