Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 将参数传递到where子句using为NULL或Coalesce_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 将参数传递到where子句using为NULL或Coalesce

Sql 将参数传递到where子句using为NULL或Coalesce,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想将参数@CompanyID传递到where子句中以过滤结果。但有时该值可能是null,因此我希望返回所有记录。我找到了两种方法,但不确定哪一种是最安全的 版本1 SELECT ProductName, CompanyID FROM Products WHERE (@CompanyID IS NULL OR CompanyID = @CompanyID) 版本2 SELECT ProductName, CompanyID FROM Products WHERE CompanyID =

我想将参数
@CompanyID
传递到
where
子句中以过滤结果。但有时该值可能是
null
,因此我希望返回所有记录。我找到了两种方法,但不确定哪一种是最安全的

版本1

SELECT ProductName, CompanyID 
FROM Products 
WHERE (@CompanyID IS NULL OR CompanyID = @CompanyID)
版本2

SELECT ProductName, CompanyID 
FROM Products 
WHERE CompanyID = COALESCE(@CompanyID, CompanyID)
我发现第一个版本是最快的,但我也发现在其他使用类似方法的表中,我得到了不同的结果集。我不太明白两者之间的区别


有人能解释一下吗?

第二个版本不是正确的SQL(用于SQL Server)。它需要一个接线员。大概是:

SELECT ProductName, CompanyID 
FROM Products 
WHERE COALESCE(@CompanyID, CompanyID) = CompanyID;
第一个版本是正确的。如果您在
公司ID
上有索引,您可能会发现这样做更快:

SELECT * 
FROM Products 
WHERE CompanyID = @CompanyID
UNION ALL
SELECT * 
FROM Products 
WHERE @CompanyID IS NULL;

值得注意的是,使用语法
([Column]=@Value或[Column]为NULL)
比使用
ISNULL([Column],@Value)=@Value
(或使用
合并
)要好得多

这是因为使用该函数会导致查询变得不可搜索;所以不会使用索引。第一个表达式是SARGable,因此性能更好


只需添加这一点,因为OP声明“我发现第一个版本是最快的”,并想详细说明原因(尽管目前声明不完整,但我猜这更多是由于用户错误和无知)。

好吧,两个查询都处理相同的两个场景-
在一个场景中,
@CompanyID
包含一个值,
在第二个
@CompanyID
中包含
NULL

对于这两个查询,第一个场景将返回相同的结果集-因为 如果
@CompanyId
包含一个值,则两者都将返回
CompanyId=@CompanyId
所在的所有行,但是第一个查询可能会更快地返回该行(在我的答案末尾有更多关于该行的信息)

然而,第二种情况是,查询开始表现出不同的行为

首先,这就是为什么会得到不同的结果集:

结果集的差异

版本1

SELECT ProductName, CompanyID 
FROM Products 
WHERE (@CompanyID IS NULL OR CompanyID = @CompanyID)
@CompanyID
为空时,where子句将不会过滤掉任何行,并且将返回表中的所有记录

版本2

SELECT ProductName, CompanyID 
FROM Products 
WHERE CompanyID = COALESCE(@CompanyID, CompanyID)
@CompanyID
为null时,where子句将过滤掉
CompanyID
为null的所有行,因为
null=null
的结果实际上是
未知的
,任何带有
null=null
的查询都不会返回结果,除非设置为
OFF
(你真的不应该这么做,因为它已经过时了)

索引使用情况

从第一个版本可能会得到更快的结果,因为在where子句中的列上使用任何函数都会阻止SQL Server使用此列上可能有的任何索引。 您可以在MSSql提示中阅读有关它的更多信息

结论

版本1比版本2好。
即使您不想返回
companyId
为null的记录,也最好以
where(@companyId为null或companyId=@companyId)的形式写入使用第二个版本时,CompanyID不为NULL。

对于第一个版本,第二个版本的语法无效。如果不提供有效的语法和数据来复制,则无法解释不同的结果。@Papazzi这是一个疏忽。我添加了正确的语法。请注意细节。为什么CompanyID位于
=
的另一边?为什么第一个是帕伦斯。像这样的东西会导致愚蠢的东西。然后我也不知道,因为我有isnull执行得更快的例子。
可能会导致一个丑陋的查询计划。@Papazzi我对这种不知道的评论是因为OP的表达式是
WHERE COALESCE(@Value,[Column])
(所以它不是布尔表达式),与可搜索性无关。
可能会导致查询lan不好,这很可能是由于其他原因(如参数嗅探或奇数索引),前提是您没有大量的
s。如果您这样做,则听起来像是“一网打尽”无论哪种方式,它都不会改变
ISNULL
COALESCE
都不可搜索的事实。