【问题标题】:Sargable queries using ISNULL in TSQL在 SQL 中使用 ISNULL 的 Sargable 查询
【发布时间】:2011-02-17 01:14:58
【问题描述】:

我希望在我的查询中防止非 sargable 表达式,这是检查 null 条件的更好方法吗?

AND c.Account IS NOT NULL 
AND c.Account <> ''

AND ISNULL(c.Account,'') <> ''

我突然意识到Account 来自LEFT JOIN,所以它可能为空。我想要它们只相交的情况,这意味着我真的应该只使用INNER JOIN 吧?谢谢你的脸;)

但是,忽略了令人作呕的自我实现,我仍然想知道在我无法将 Account 设为 NOT NULL 列的一般情况下的答案。

【问题讨论】:

  • 最好将Account字段设置为NOT NULL,因为这些值对您的意义相同,最好使用COALESCE,因为它是SQL标准的一部分。
  • 空字符串等价于 NULL ?哎呀!
  • @lukled ~ 所以在哪里使用 COALESCE 会更好?
  • @Lukled:NULL 不是一个值。 Null 表示未知或缺失。空字符串意味着你知道它并且它是空的。
  • @Mitch Wheat:告诉 Oracle 的工程师:) 在 Oracle 中,空字符串等于 null。

标签: sql-server tsql isnull


【解决方案1】:

只需使用WHERE c.Account &lt;&gt; ''

对于null 或空字符串,这不会评估为真,并且可能会使用Account 上的范围搜索来评估。

使用ISNULLCOALESCE 会使表达式不可分割并且无论如何都不需要。

如果你想区分真正的空字符串和完全由空格组成的字符串,你可以使用

 WHERE c.Account IS NOT NULL AND DATALENGTH(c.Account) > 0

它结合了一个允许索引寻求跳过索引中的空值的 sargable 谓词与一个针对剩余值的 unsargable 谓词。

【讨论】:

    【解决方案2】:

    C.Account &lt;&gt; '' 等价于ISNULL( c.Account, '' ) &lt;&gt; ''

    SQL Server 可能足够聪明,可以将 IsNull 转换为等效的 SARG 表达式,但如果您一心想要使用函数,那么 Coalesce 是更好的选择,因为它是 SQL 标准的一部分,允许多个值(而不仅仅是两个与 IsNull)并避免使用很可能是 Microsoft 在 IsNull 中设计的最令人困惑的函数名称。

    【讨论】:

    • 您为什么认为 SQL-Server 足够聪明,可以将其转换为 sargable 表达式? As far as i know ISNULL/COALESCE 是不可分割的,应替换为 IS NULL OR &lt;&gt; ''。此外,COALESCE 在 sql-server 中仍然存在严重错误,因此在您需要 COLESCE 之前,应该首选ISNULL。它被翻译成一个CASE,它会计算两次。 connect.microsoft.com/SQLServer/feedback/details/336002/…
    • @TimSchmelter - RE:IsNull,IMO,应该永远使用 IsNull。借口为零。除了它是有史以来设计的最可怕的命名函数之外,它不符合 ANSI,而且您注意到的情况是五年前的情况,仅适用于使用子查询时(因此它可能已修复)。最好将其写为案例语句而不是使用 IsNull。我希望 MS 会完全弃用它。至于它是否是 sargable,我说 MS 可能 足够聪明,因为它将函数转换为 case 表达式,但解析器可能无法处理。
    • 错误状态仍然有效。我仍在使用 SQL-Server 2005,至少它没有修复。此查询返回两个错误消息而不是一个(与 ISNULL 一样):SELECT COALESCE(xyz, 0) FROM sys.objects。大多数人不知道,但每个人都建议使用COALESCE 而不是ISNULL。即使没有子查询 ISNULL 也可以减少 20-30% 的 CPU 来运行。
    • IsNull 实际上是 Sybase 提供给 Microsoft 的。也许它是微软购买过的任何产品中最容易混淆的功能名称
    【解决方案3】:

    COALESCE IS SARGABLE 因为它只是一个快捷表达式(相当于使用CASE WHEN IS NOT NULL THEN ELSE...)。

    ISNULL 是一个内置函数,因此ISNULL 不可搜索

    【讨论】:

      猜你喜欢
      • 2017-04-19
      • 2018-12-14
      • 2018-09-19
      • 1970-01-01
      • 2017-04-01
      • 1970-01-01
      • 2019-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多