2013-02-07 64 views
1

请考虑采用某些参数的以下示例过程。存储过程中可选参数的最佳解决方案

Create Procedure CustomerSearch(
@Name  nVarChar(100) = Null, 
@Phone  nVarChar(100) = Null, 
@Address nVarChar(100) = Null, 
) 
As 

Select * 
     From dbo.CustomerView 
     Where (@Name  is Null or Name  = @Name) And 
       (@Phone  is Null or Phone = @Phone) And 
       (@Address is Null or Address = @Address) 

因为参数的值可能为空,所以我找到两个解决方案来处理它。

  1. 使用或contition这样的: (@Name为空或名称= @Name)
  2. 使用动态SQL,并添加条件进行查询,如果参数值不为空。

在CustomerView视图中存在多个表连接,并且此表具有大量数据并且性能非常重要。解决方案1有开销(执行计划)。由于某些原因,我无法使用动态sql。有更好的方法来建立这个查询?

当我使用条件@Name是Null或Name = @Name)而不是Name = @Name并查看执行计划时,索引查找成本增加。

+3

您可能会发现此资源有用:[T-SQL中的动态搜索条件](http://www.sommarskog.se/dyn-search.html)。 –

回答

2

你的代码工作正常,为了你的情况,我会将参数包装在NULLIF(@Parameter,'')中以防止空白被比较。

下面是编写查询的另一种方法。如果该参数为空或为空,则会将列与自身进行比较,总是为真。

Name = COALESCE(NULLIF(@Name,''),Name) 

http://sqlfiddle.com/#!3/4ff42/1

2

您上面张贴的代码完全可以接受。如果性能出现问题,请确保名称,电话和地址列上有索引。

+0

我在这个列上创建了索引,它不是我的问题。当我运行查询时需要太多的时间,并且当我查看执行计划时(检查空参数)采用进程与使用name = @name条件。 –

+0

您能否提供创建的索引? – UnhandledExcepSean

+0

我创建了所有列的单一索引,名称索引,手机索引和... –

1

你可能也想看看添加OPTION (RECOMPILE)到您的存储过程的结束。

无论何时存储过程第一次在SQL Server中运行,它都经过优化,查询计划被编译并缓存在SQL Server的内存中。

MSDN article

RECOMPILE
指示SQL Server数据库引擎来丢弃它执行后查询生成的计划,迫使查询优化器下一次重新编译查询计划相同的查询被执行。没有指定RECOMPILE,数据库引擎会缓存查询计划并重新使用它们。编译查询计划时,查询提示使用查询中任何局部变量的当前值,并且如果查询位于存储过程中,则将当前值传递给任何参数。
RECOMPILE是创建使用WITH RECOMPILE子句的存储过程时的有用替代方法,因为只有存储过程中的一部分查询而不是整个存储过程必须重新编译时。有关更多信息,请参阅重新编译存储过程。 当您创建计划指南时,RECOMPILE也很有用。

+0

好的。请注意,我的问题是条件(@Name为Null或Name = @Name)而不是Name = @Name索引查找成本增加。 –