【问题标题】:isnull vs is nullisnull vs 为空
【发布时间】:2010-06-25 13:10:04
【问题描述】:

我注意到一些工作中的查询以及关于 SO 的查询都使用了以下形式的限制:

isnull(name,'') <> ''

人们这样做有什么特别的原因,而不是更简洁

name is not null

这是遗留问题还是性能问题?

【问题讨论】:

  • Martin Smith 是对的,如果您准确地引用了代码。如果它实际上类似于 isnull(name,'') @name 那么您将阻止 SQL 使用任何索引,但您得到的结果更像 Donnie 所描述的
  • @Matt:是的,我在示例中给出的代码中犯了一个错误。现在已修复。

标签: sql sql-server sql-server-2005 tsql


【解决方案1】:
where isnull(name,'') <> ''

等价于

where name is not null and name <> '' 

相当于

where name <> ''

(如果名称 IS NULL 最终表达式的计算结果为未知且未返回该行)

ISNULL 模式的使用将导致扫描并且效率较低,如下面的测试所示。

SELECT ca.[name],
       [number],
       [type],
       [low],
       [high],
       [status]
INTO   TestTable
FROM   [master].[dbo].[spt_values]
       CROSS APPLY (SELECT [name]
                    UNION ALL
                    SELECT ''
                    UNION ALL
                    SELECT NULL) ca 


CREATE NONCLUSTERED INDEX IX_TestTable ON dbo.TestTable(name)

GO


SELECT name FROM TestTable WHERE isnull(name,'') <> ''

SELECT name FROM TestTable WHERE name is not null and name <> ''
/*Can be simplified to just WHERE name <> '' */

这应该会给你你需要的执行计划。

【讨论】:

  • "使用这种模式...效率较低..." 模式是使用 ISNULL 还是 IS NULL...OR = 构造?
  • @KarlKieninger - 使用ISNULL 的模式 - 最初有一些执行计划图像使这一点更清晰。会再生他们..
【解决方案2】:
is not null

只会检查字段是否不为空。如果该字段包含空字符串,则该字段不再为空。

isnull(name, '') <> name

检查空字符串和空字符串。

【讨论】:

    【解决方案3】:

    isnull(name,'') &lt;&gt; :name(name is null or name &lt;&gt; :name) 的简写(假设:name 从不包含空字符串,因此为什么这样的简写可能不好)。

    性能方面,这取决于。 where 子句中的 or 语句可能会产生极差的性能。但是,列上的函数会损害索引的使用。像往常一样:个人资料。

    【讨论】:

      【解决方案4】:
      isnull(name,'') <> name
      

      嗯,我可以看到他们使用这个,因为这样如果名称不匹配或为空,它会返回失败的比较。这真的意味着:name is nullname &lt;&gt; name

      name is not null 只是检查名称是否为空。

      【讨论】:

        【解决方案5】:

        它们的意思不同。

        name is not null 
        

        这会检查名称字段为空的记录

        isnull(name,'') <> name  
        

        这一项将空字段的值更改为空字符串,以便可以在比较中使用它们。在 SQL Server 中(但我认为不是在 Oracle 中),如果一个值为 null 并且用于比较等式或不等式,则不会将其视为 null,因为 null 意味着我不知道该值,因此不是实际值。因此,如果您想确保在进行比较时考虑空记录,则需要 ISNULL 或 COALESCE(这是 ASCII STANDARD 术语,因为 ISNULL 不适用于所有数据库)。

        你应该看的是

        isnull(a.name,'') <> b.name  
        

        a.name b.name

        然后您就会明白为什么需要 ISNULL 才能获得正确的结果。

        【讨论】:

          【解决方案6】:

          我显然误读了您的问题。因此,让我来尝试我的第一个答案并尝试这个:

          isnull(name,'') <> ''
          

          是一个错误的捷径

          name is not null and name <> ''
          

          【讨论】:

            【解决方案7】:

            其他人指出了功能差异。至于性能问题,在 Postgres 中我发现——哦,我应该提到 Postgres 有一个函数“coalesce”,它相当于在其他一些 SQL 方言中发现的“isnull”——但在 Postgres 中,说

            where coalesce(foobar,'')=''
            

            明显快于

            where foobar is null or foobar=''
            

            另外,说起来会快很多

             where foobar>''
            

            结束

            where foobar!=''
            

            大于测试可以使用索引并因此跳过所有空白,而不等于测试必须执行完整的文件读取。 (假设您在该字段上有一个索引,并且没有优先使用其他索引。)

            【讨论】:

              【解决方案8】:

              此外,如果您想使用该列上的索引,请使用

              name is not null and name <> '' 
              

              【讨论】:

                【解决方案9】:

                这两个查询不一样。比如我没有中间名,这是一个已知的事实,可以存储为

                MiddleName=''
                

                但是,如果我们不知道某人的中间名,我们可以存储 NULL。 所以,ISNULL(MiddleName, '') 的意思是“没有已知中间名的人”。

                【讨论】:

                  【解决方案10】:

                  处理空字符串和NULL。虽然能够使用一条语句很好,但isnull 是专有语法。我会使用可移植的标准 SQL 来编写这个

                  NULLIF(name, '') IS NOT NULL
                  

                  【讨论】:

                    猜你喜欢
                    • 2011-06-09
                    • 2020-11-08
                    • 2020-11-03
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多