SQL为什么要使用isnull(field,'')<> ''?

时间:2012-10-25 18:18:42

标签: sql sql-server null sql-server-2000 string

我正在审查我继承的一些代码,我发现了这样的一行:

And isnull(IH.CustomerItemNumber, '') <> ''

我的前任中的哪一位似乎曾在大量的where子句或join子句中使用过。在我看来,这是一个不必要的函数调用,因此性能损失,因为NULL永远不会等于空字符串'',对吗?

具体来说,我从特定查询中的join子句中取出了这个,并且性能显着提高(从46-49秒到1-3之间)。

将其替换为AND IH.CustomerItemNumber <> ''

我的评估是否正确?这是多余的,缓慢的,可以删除?在什么情况下这段代码可能是有益的?

编辑:那么,NULL是否可以等于空字符串?

4 个答案:

答案 0 :(得分:5)

这在语义上与:

相同
And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null

因此检查列是否为空且不是空字符串。可能很重要。

<强>更新

在这种情况下,因为我们正在寻找字符串文字(空字符串)的不相等,所以至少有三个语义正确的选项:

  • And IH.CustomerItemNumber <> ''
  • And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null
  • And isnull(IH.CustomerItemNumber, '') <> ''

第一个将返回与其他两个相同的结果集,因为<> ''将无法匹配null,无论ansi_nulls设置如何。

在开发系统的快速测试中,第一个和第二个都使用索引搜索。第一个非常轻微地在一些非常简化的测试中胜过第二个

第三个,因为它添加了一个函数调用,可能不会像其他函数那样使用索引,所以这可能是最糟糕的选择。也就是说,在快速测试中,isnull能够使用索引扫描。进一步将Is Not Null添加到第三个选择实际上加速了它并将其移动到索引搜索。去图(GO!GO!查询优化器!)。

与@Gordon一样,我也会多次选择第二个选项,因为它会更好地表达我对其他开发人员(或我自己)的意图,如果我们检查与另一个列的相等性,那么这将是一个更好的做法。 null(想想潜在的ansi_nulls)。

为了完整起见:

  • And nullif(IH.CustomerItemNumber, '') is not null
  • And case when IH.CustomerItemNumber = '' then null else IH.CustomerItemNumber end is not null
  • And case IH.CustomerItemNumber when '' then null else IH.CustomerItemNumber end is not null

在SQL Server中,所有解释方式都完全相同(据我所知)并执行与上面第三个选项相同的操作。

答案 1 :(得分:4)

代码存在的原因可能是因为应用程序的历史记录。也许在某个时间点,字段中允许NULL。然后,用空字符串替换它们。

代码效率低下的原因是由于连接的优化。 ISNULL()及其ANSI标准等效COALESCE()通常会增加查询处理的开销。 (似乎在某些版本的SQl Server中,COALESCE()会对第一个参数进行两次计算,如果它是子查询则会出现问题。)

我的猜测是该字段有一个索引。当单独使用该字段时,SQL Server知道使用索引进行连接。在函数调用中包含索引时使用索引是不够智能的。正是连接优化会降低查询速度,而不是函数调用的开销。

就个人而言,如果性能相同,我更喜欢具有显式NULL检查的表单:

IH.CustomerItemNumber <> '' and IH.CustomerItemNumber is not null

明确关于NULL处理只能帮助您将来维护代码。

答案 2 :(得分:1)

您可以使用NULL检查:

And (IH.CustomerItemNumber IS NOT NULL) AND (IH.CustomerItemNumber <> '')

顺便说一句,   ISNULL ( check_expression , replacement_value ) - 使用指定的替换值替换NULL。

在你的情况下,如果IH.CustomerItemNumber的值为null,那么它将被空值替换,然后将其与空字符串进行比较。

答案 3 :(得分:0)

  

因为NULL永远不会等于空字符串'',对吗?

NULL也永远不会不等于到空字符串......它既是同时又不是全部同时。它传达了一个你不确定的状态。