我有一个SQL查询,它接受以下参数:
@SearchFor nvarchar(200) = null
,@SearchInLat Decimal(18,15) = null
,@SearchInLng Decimal(18,15) = null
,@SearchActivity int = null
,@SearchOffers bit = null
,@StartRow int
,@EndRow int
变量@SearchFor
,@SearchActivity
,@SearchOffers
可以为null或非null。 @SearchInLat
和@SearchInLng
必须都为null,或者两者都有值。
我不打算将整个查询发布为无聊且难以阅读,但WHERE子句的形状如下:
( -- filter by activity --
(@SearchActivity IS NULL)
OR (@SearchActivity = Activities.ActivityID)
)
AND ( -- filter by Location --
(@SearchInLat is NULL AND @SearchInLng is NULL)
OR ( ... )
)
AND ( -- filter by activity --
@SearchActivity is NULL
OR ( ... )
)
AND ( -- filter by has offers --
@SearchOffers is NULL
OR ( ... )
)
AND (
... -- more stuff
)
我已经读过,这是构建查询的一种不好的方法 - SqlServer在制定一个有效的执行计划方面遇到了麻烦,因为我正在寻找其他方法来实现它。
我看到两种方法:
WHERE
子句仅包含相关参数的过滤器。这个问题是它意味着不能通过存储过程访问数据库,就像其他所有东西一样。我该怎么办?或者我应该继续,因为我目前在做什么?我有OPTION (RECOMPILE)
设置程序,但我听说这在Server 2005中不起作用。而且,我打算在这个proc中添加更多参数,所以我想确保我有什么解决方案是相当可扩展的。
答案 0 :(得分:4)
答案是使用DynamicSQL(无论是在客户端,还是在使用sp_executesql
的SP中),但原因很长,所以这里有一个链接......
Dynamic Search Conditions in T-SQL
非常短的版本是单一尺寸不适合所有。由于优化器为一个查询创建了一个计划,因此速度很慢。所以解决方案是继续使用参数化查询(用于执行计划缓存),但是对于可能发生的不同类型的搜索有很多查询。
答案 1 :(得分:1)
也许替代方案可能是执行几个单独的select语句?
e.g。
( -- filter by activity --
if @SearchActivity is not null
insert into tmpTable (<columns>)
select *
from myTable
where (@SearchActivity = Activities.ActivityID)
)
( -- filter by Location --
if @SearchInLat is not null and @SearchInLng is not null
insert into tmpTable (<columns>)
select *
from myTable
where (latCol = @SearchInLat AND lngCol = @SearchInLng)
等...
然后选择临时表以返回最终结果集。
我不确定这对于优化器和查询计划是如何工作的,但是每个单独的选择都非常简单,并且可以利用您在每列上创建的索引,这些索引应该非常快。
根据您的要求,在临时表上创建主键以允许您在每次选择时加入它(以避免重复)也是有意义的。
答案 2 :(得分:0)
首先看一下表演,就像其他人说的那样。
如果可能,您可以使用IF子句根据提供的参数简化查询。
如果您发现经常重复某些代码,也可以使用函数或视图来封装一些代码。