存储过程大的where子句或多个过程

时间:2015-02-22 14:44:50

标签: c# sql .net sql-server stored-procedures

有一个大查询或N个小查询会通过代码调用吗?

例如,选择具有多个参数的所有客户:

select
   id,
   name,
   firstname,
   city,
   birthday,
   ...
from dbo.Customers
where (@Name is null or name like @Name)
and (@FirstName is null or firstname like @FirstName )
and (@City is null or city @City)
and (@Birthday is null or birthday = @Birthday)

或者也有多个存储过程,如

select
   id,
   name,
   firstname,
   city,
   birthday,
   ...
from dbo.Customers
where (@Name is null or name like @Name)
and (@FirstName is null or firstname like @FirstName)

select
   id,
   name,
   firstname,
   city,
   birthday,
   ...
from dbo.Customers
where city like @City

select
   id,
   name,
   firstname,
   city,
   birthday,
   ...
from dbo.Customers
where  birthday = @Birthday

2 个答案:

答案 0 :(得分:1)

如果你有一个小桌子(数百或几千行),那么一个带有复杂where子句的查询就可以了:

where (@Name is null or name like @Name) and
      (@FirstName is null or firstname like @FirstName ) and
      (@City is null or city @City) and
      (@Birthday is null or birthday = @Birthday)

此查询无法利用索引,因此必须执行全表扫描。

如果表上有索引并且您希望查询使用它们,那么动态SQL可能就是这样:

声明@sql varchar(max);

set @sql = <your query here without the `where` clause>.

select @sql = ('where 1=1 and ' +
               (case when @Name is not null then 'and name like @Name' else '' end) +
               . . .
              );

exec sp_execute_sql @sql, N'@name varchar(255), @firstname varchar(255) . . . ',
     @name = @name, @firstname = @firstname, . . .;

这将从查询中删除or条件,使其更有可能使用适当的索引。

答案 1 :(得分:1)

创建具有以下几个可选条件的过程时:

(@Name is null or name like @Name) and 
(@FirstName is null or firstname like @FirstName)

问题是SQL Server无法为任何字段使用索引,因为查询计划是在第一次执行时创建的,并且会在下次存储并重新使用。

如果表很小,聚集索引扫描的成本可能不重要,但如果表很大或经常调用过程,您将有几个选择:

1)使用“option(重新编译)”。这将每次制定一个新计划,然后SQL Server可以消除计划中未提供的标准。每次创建新计划都会导致额外的CPU花费。如果我没记错的话,这可以从SQL Server 2008开始工作。

2)为已经给出值的情况创建几个过程,或者在一个过程中为if-blocks内的单独select语句创建。这样可以存储和重复使用计划

3)使用变量+ sp_execute_sql创建动态SQL,如@Gordon Linoff的回答

相关问题