根据传递的参数过滤where子句中的列?

时间:2018-08-09 12:10:43

标签: sql sql-server sql-server-2008 where-clause

我有必须基于函数中传递的参数进行筛选的查询。这将决定我是否根据NameCode提取记录或提取All记录。这是查询的示例:

DECLARE @FilterBy INTEGER = <cfqueryparam value="#trim(arguments.frm_filterby)#" cfsqltype="cf_sql_integer" />;

SELECT RecID, Status, Code, Name
FROM Dictionary WITH (NOLOCK)       
WHERE 
    (@FilterBy = 1 AND Name LIKE <cfqueryparam value="#trim(arguments.frm_search)#" cfsqltype="cf_sql_varchar" maxlength="50" />)
    OR 
    (@FilterBy = 2 AND Code = <cfqueryparam value="#trim(arguments.frm_search)#" cfsqltype="cf_sql_char" maxlength="2" />)
    OR 
    (@FilterBy = 3 AND 1 = 1)
ORDER BY Name

如您所见,我声明了用于filter的变量并将其设置为整数,然后使用OR来过滤列。我想知道这是否适合这种情况,还是有更好的方法呢?是否可以使用CASE语句来做到这一点?

1 个答案:

答案 0 :(得分:1)

对于全部查询而言,这是一种非常好的方法。

但是,由于SQL Server会缓存它为查询创建的第一个查询计划,而对于其他参数值来说,它并不是最佳的查询计划,因此,笼统查询通常在性能方面存在问题。

在这种情况下,@FilterBy = 1的优化查询计划可能与@FilterBy = 2@FilterBy = 3的优化查询计划大不相同。

基本上,最好为每个搜索编写不同的过程。 (尽管请记住,这并非始终是一个有效的选项-假设您没有3个搜索选项,而是要搜索16列,每个变量一个,而查询中的其他所有内容都相同...)

盖尔·肖(Gail Shaw)在Sql In the wild上写了它,而亚伦·伯特兰(Aaron Bertrand)则写了它,将这种类型的查询称为"Kitchen Sink" procedure.

此外,您的查询使用NOLOCK查询提示,这通常是不良设计的标志。 艾伦·伯特兰(Aaron Bertrand)再次写了这个-Bad habits : Putting NOLOCK everywhere-您不仅要担心读脏东西。

最后一件事,您的最后一个条件是(@FilterBy = 3 AND 1 = 1)-当然,AND 1 = 1完全多余。