我有必须基于函数中传递的参数进行筛选的查询。这将决定我是否根据Name
,Code
提取记录或提取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
语句来做到这一点?
答案 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
完全多余。