2

考虑遵循采用一些参数的示例过程。

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. 像这样使用或使用:(@Name 为 Null 或 Name = @Name)
  2. 如果参数值不为空,则使用动态sql并添加条件进行查询。

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

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

4

3 回答 3

2

您上面发布的代码是完全可以接受的。如果性能是一个问题,请确保 Name、Phone 和 Address 列上有索引。

于 2013-02-07T17:50:14.610 回答
2

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

这也是编写查询的另一种方式。如果参数为空或 null,它将将该列与自身进行比较,这始终为真。

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

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

于 2013-02-07T18:40:04.923 回答
1

您可能还想查看添加OPTION (RECOMPILE) 到存储过程的末尾。

每当第一次在 SQL Server 中运行存储过程时,都会对其进行优化,并编译查询计划并将其缓存在 SQL Server 的内存中。

来自MSDN 文章

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

于 2013-02-07T18:52:23.163 回答