动态查询的SQL Server替代方案

动态查询的SQL Server替代方案,sql,sql-server,dynamic-sql,Sql,Sql Server,Dynamic Sql,我想知道我们有哪些选项不进行动态查询 例如: IF @Mail <> '' BEGIN SELECT @Where = @Where + ' AND Mail = @Mail ' END ELSE IF @Phone <> '' BEGIN SELECT @Where = @Where + ' AND Phone like ''%'' + @Phone ' END 如果@Mail“” 开始 选择@Where=@Where+'和Mail=@Mail' 结

我想知道我们有哪些选项不进行动态查询

例如:

IF @Mail <> ''
BEGIN
    SELECT @Where = @Where + ' AND Mail =  @Mail '
END
ELSE IF @Phone <> ''
BEGIN
    SELECT @Where = @Where + ' AND Phone like ''%'' + @Phone '
END
如果@Mail“”
开始
选择@Where=@Where+'和Mail=@Mail'
结束
如果@Phone“”
开始
选择@Where=@Where+'和类似于'%''+@Phone'的电话
结束
我不想这样做,我想避免动态查询,如果有人可以帮助我


顺便说一下,我想通过
邮件
进行过滤,但是如果
邮件
不存在,那么我必须通过
电话
进行过滤,但决不能同时通过这两种方式进行过滤

就性能而言,使用动态查询可能会更好。简单的查询通常更容易优化

但是,您可以将
where
子句表述为:

where . . . AND
      (@Mail = '' or mail = @mail) AND
      (@Phone = '' or Phone like '%' + @Phone)
注意:
NULL
值通常用于表示“全部”。因此,更典型的公式是:

WHERE . . . AND
      (@Mail IS NULL or mail = @mail) AND
      (@Phone IS NULL or Phone like '%' + @Phone)

为什么不使用CASE呢

下面是可以帮助您进行此查询的URL


对于多个筛选器,动态SQL很有可能表现得更好,因为ORs和性能通常在SQL查询中无法协调

但是,如果“no filter value”上的filters为NULL,则可以这样编写查询:

SELECT Mail, Phone, <other columns here>
FROM table
WHERE Mail = COALESCE(@Mail, Mail)
   AND Phone LIKE (COALESCE('%' + @Phone, Phone)
选择邮件、电话、,
从桌子上
其中Mail=COALESCE(@Mail,Mail)
和类似电话的(合并('%'+@Phone,Phone)
使用
nullif(@Mail,)
可以轻松地将所有
'
值转换为
NULL
。此外,这将均匀地处理
'
NULL

您可以尝试此方法

AND ((ISNULL(@Mail,'') = '' or mail = @mail) OR (ISNULL(@Phone,'') = '' or Phone like '%' + @Phone))

如果您想提高性能,最好的解决方案是对每种情况进行单独的查询

Gordon的解决方案很好,但SQL server不会在筛选所依据的列上使用任何索引。
可以通过添加选项(重新编译)来增强使用索引的能力,但这将导致每次运行查询时重新编译查询。如果表中有很多行(并且在列上定义了索引),则会显著提高性能,但会降低行数较少(或没有索引)的表的性能-它将具有与动态查询基本相同的性能。

(1)我认为
phone
逻辑不正确,因为表达式不包括
@phone
(2)我添加了SQL Server标记,因为语法看起来像SQL Server。除了可读性之外,动态SQL没有什么错。您不能在代码中建立动态SQL而不是存储的进程吗?考虑使用ORM吗?如果邮件和电话不是NULL会发生什么情况,将用两个还是仅用邮件做哪里?首先,我想用邮件过滤,但是如果为null,则通过电话进行筛选,但决不能同时使用两者。谢谢,但我的问题是,如果邮件和电话均不为null,则查询将仅通过电子邮件或通过电话进行选择?谢谢该查询应适用于所有组合:两者均为null,只有一个为null,两个均不为null。此外,它还应扩展到任意数量的筛选器,尽管性能性能可能会降低很多。isnull方法唯一的缺点是它会创建糟糕的查询计划。@标记-这是正确的。这就是为什么我会直接使用动态查询。或者更好,使用LINQ(动态LINQ)或类似的方法来生成查询。