【问题标题】:To check on NULL or 0检查 NULL 或 0
【发布时间】:2010-10-21 14:00:21
【问题描述】:

在 SQL 中检查 NULL 或 0 的值更快的是什么

我想用最快的方法检查表中是否已经存在值。

例如哪个更快:

IF ((SELECT ID FROM [SomeTable].[dbo].[BlockedSubscriberNumbers] 
     WHERE VALUE = @myVal) is null )
BEGIN
....
END
ELSE
BEGIN
....
END

IF ((SELECT COUNT(ID) FROM [SomeTable].[dbo].[BlockedSubscriberNumbers]
     WHERE VALUE = @myVal) > 0 )
BEGIN
....
END
ELSE
BEGIN
....
END

在 T-SQL 中也扮演着频繁累积案例必须出现的角色。我的意思是它会更快,在大多数情况下它会失败进入 IF 块,如果它主要进入 ELSE 会更慢。

【问题讨论】:

  • 这是两个不同的查询,会返回不同的结果。
  • 这可能是个好消息,但请记住过早的优化是万恶之源。这两种方式都可以工作,具体取决于您的要求。选一个。 任何一种方法都绝对不是你的性能问题(如果你有一个开始的话)。
  • 您是否保证您的选择将始终返回 0 或 1 个结果?如果查询返回超过 1 行,您将收到错误消息。
  • @Joe ID 为主键,不能有多个值。
  • @Incognito:如果你告诉我 VALUE 是主键,我会没事的。我仍然看到 VALUE=@myVal 可能适用于多个 ID。

标签: sql sql-server database tsql


【解决方案1】:

这些实际上会做不同的事情,你不能在 SQL 中检查 NULL 是否大于 0。

你应该做的是这个。

    IF (ISNULL((SELECT ID FROM [SomeTable].[dbo].[BlockedSubscriberNumbers] 
         WHERE VALUE = @myVal), 0) > 0 )
    BEGIN
    ....
    END
    ELSE
    BEGIN
    ....
    END

你的意思是等于 0 吗?因为你的问题是

在 SQL 中检查值更快的是什么 对于 NULL 或 0

这部分是关于 Joe 关于多个结果集的评论

您可以使用 ISNULL 对 Select ID 执行某种聚合函数,以确定是否有任何值大于 0(当然假设您的所有值都大于 0)。

关于根据 OP 评论确定是否有任何行包含该信息

IF (Select Count(ID) from [SomeTable].[dbo].[BlockedSubscriberNumbers] Where Value = @myVal) = 0 应该告诉你是否有包含该值的行

最终编辑

只需使用Exists

If Exists(Select ID From [SomeTable].[dbo].BlockedSubscriberNumbers] Where Values = @myVal)

【讨论】:

  • 更仔细地查看原始查询中的括号。 OP 不是在尝试测试 @myVal>0,而是在尝试测试查询的结果 ID。
  • @Joe Stefanelli,很好的修复
  • 其实我不关心比较是NULL大于0。如果查询的结果是NULL,它会和0比较它会去ELSE块,这意味着没有价值在等于@myVal 的表中。总而言之,我只需要检查该值是否已经存在。
  • 那么您是在尝试获取查询返回的行数吗?
  • @msarchet 一般来说,我需要检查是否有任何记录。有多少行并不重要。无论如何,它可以打开或没有,因为 VALUE 字段是唯一的。
【解决方案2】:

检查 NULL 比检查 0 快得多,但我认为,对于这些查询,我们讨论的是不同的事情:它们产生不同的结果。

【讨论】:

    【解决方案3】:

    IMO,表中的每条记录/行都包含 NULL BITMAP (2 个字节,其中的每个位说明该行中的一个/每个列的值是否为空),所以在选择之前/reading real stored value 这个读取数据的过程通过了对来自这个 NULL 位图的相应位的检查/读取。

    在 NULL 的情况下(或者,换句话说,“不为空”检查),读取过程在此阶段停止,而其他选择/检查/比较可能(或可能不,这取决于)继续,所以“是空检查”不能更慢。甚至,行末尾的 NULL 值甚至没有被存储,它们不占用存储空间。它们实际上是,有时几乎什么都不是。

    不过,问题在于您的 TSQL 示例和问题本身存在歧义,可能有多种解释和答案。

    【讨论】:

      【解决方案4】:

      对于任何想要在查询中找到它的人,您可以执行以下操作:

      SELECT ISNULL(NULLIF(primaryValue,0),secondaryValue) as Value FROM SomeTable

      这里的 NULLIF 将仅在 primaryValue 已经为 NULL 或为 0 时将其返回为 NULL。如果 primaryValue 为 NULL,则 ISNULL 将返回 secondaryValue

      因此,如果 primaryValue 为 NULL 或 0,那么它将返回 secondaryValue

      【讨论】:

        【解决方案5】:

        EXISTS 可能比 COUNT 更快,特别是如果您要查找的行非常大,而且您不应该过多地关注微优化。首先争取代码的可读性,以便其他阅读您的代码的人可以轻松地收集您查询的意图。无论如何,即使 COUNT 已经找到您要查找的值,它仍会尝试循环行。 EXISTS 是一个指令,让您的 RDBMS 在符合您的条件时立即停止搜索。

        此外,您的代码的逻辑是如果某些东西存在,这就是为什么要在语言中引入一流的语言结构来促进这一点。当然,数据库供应商的工程师会努力优化它,因为它基本上是一个已解决的问题。您不会期望他们将其 COUNT 引擎重新用于 EXISTS 功能,如果 EXISTS 等待 COUNT 及其结果,然后检查该结果是否大于零以使 EXISTS 返回 true,那就太糟糕了.那不会发生。

        EXISTS 非常优化

        这在可读性和性能方面都更好:

        IF EXISTS(SELECT ID FROM [SomeTable].[dbo].[BlockedSubscriberNumbers] 
             WHERE VALUE = @myVal) 
        

        以下可能会导致很多行。如果您的表中有许多行满足过滤器,这将导致错误:

        IF ((SELECT ID FROM [SomeTable].[dbo].[BlockedSubscriberNumbers] 
             WHERE VALUE = @myVal) is null )
        

        该查询方法的唯一可取之处是表上的 VALUE 字段是否是主键(但假设您忘记在该表上放置主键),并且它返回两行,这不会做沉默错误,RDBMS shall balk with error,与COUNTEXISTS 方法相比,您可以更早地修复错误

        【讨论】:

          【解决方案6】:
          select (case when id is null or id=0
          then (dothis) else (dothis) end) as idState 
          from [SomeTable].[dbo].[BlockedSubscriberNumbers]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-11-30
            • 2014-08-14
            相关资源
            最近更新 更多