有一个大查询或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
答案 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的回答