代码之家  ›  专栏  ›  技术社区  ›  tato

MySQL神秘:空值与非空字符串没有区别

  •  3
  • tato  · 技术社区  · 14 年前

    为什么此查询返回0行?

    select t.f1, t.f2
    from (select null f1, 'a' f2 from dual) t
    where t.f1<>t.f2;
    

    这是我所拥有的复杂查询的精简版。我想比较包含一对一相关数据的两个表,并为某些字段选择包含不同值的行。但也可能有这样的情况:其中一个表中缺少一行。左联接正确地返回这些行的空值,但是WHERE子句错误地(或意外地)过滤了这些行。

    为什么在这种情况下,“空”与任何非空值(如“a”)都没有区别?

    让我发疯的是这个

    select t.f1, t.f2
    from (select null f1, 'a' f2 from dual) t;
    

    返回1行(如我预期的那样),但此

    select t.f1, t.f2
    from (select null f1, 'a' f2 from dual) t
    where t.f1=t.f2;
    

    返回0行!! 所以,空值不等于“a”,空值与“a”没有区别!!

    拜托。。。有人能解释一下吗?

    5 回复  |  直到 14 年前
        1
  •  5
  •   Amadan    14 年前

    确切地。 NULL 表示未知值,而不是任何特定值(它与 无效的 在C或 nil 在Ruby等中)在SQL中,如果将某些内容与未知值进行比较,结果也是未知的。你也不会得到 WHERE 条件未知。

    试试这个:

    SELECT NULL <> 2;
    

    你会看到 无效的 结果。

    试试这个:

    SELECT * FROM t WHERE NULL;
    

    即使在桌子上 t 是巨大的。

    如果你真的需要你所说的你想要的(而我不主张这样做),你可以这样做:

    SELECT T.f1, T.f2
    FROM (SELECT NULL f1, 'a' f2) T
    WHERE ((T.f1 IS NULL OR T.f2 IS NULL)
        AND (T.f1 IS NOT NULL OR T.f2 IS NOT NULL))
        OR T.f1 <> T.f2
    
        2
  •  3
  •   Daniel Vassallo    14 年前

    概念 NULL 对于新加入SQL的人来说,这是一个常见的混淆源,他们经常认为 无效的 被视为其他值。

    事实并非如此。概念上, 无效的 意思是“一个缺失的未知值”,因此它的处理方式非常不同。

    你所看到的很容易解释。请考虑以下示例:

    CREATE TABLE mytb (id int, value int);
    
    INSERT INTO mytb VALUES (1, 100);
    INSERT INTO mytb VALUES (2, 200);
    INSERT INTO mytb VALUES (3, NULL);
    INSERT INTO mytb VALUES (4, 400);
    

    上面的意思是,对于 id = 3 ,值为“未知”。它可能是 300 或者可能是 100 或者别的什么。

    因此,当您请求以下内容时:

    SELECT * FROM mytb WHERE value <> 100;
    +------+-------+
    | id   | value |
    +------+-------+
    |    2 |   200 |
    |    4 |   400 |
    +------+-------+
    2 rows in set (0.00 sec)
    

    行与 ID=3 没有返回,因为 NULL <> 100 返回“unknown”。我们不知道是不是划船 ID=3 值为100,因此表达式不返回 true . 我不回来了 false 要么。它返回“未知”( 无效的 )

    的条件 WHERE 只有当表达式为 . 当你把某物与 无效的 ,表达式不能为真。它将是“未知”。

        3
  •  1
  •   sarnold    14 年前

    SQL空值不能按您希望的方式工作: http://en.wikipedia.org/wiki/Sql_null

    简而言之, NULL = NULL 不是真的。 NULL <> NULL 不是真的。 NULL <> 1 不是真的。诸如此类。

        4
  •  0
  •   David Espart    14 年前

    尝试执行此查询:

       select * from dual where NULL = NULL
    

    它返回0行。这是因为要将值与空值进行比较,必须执行以下操作 IS NULL IS NOT NULL ,否则它将返回 .

        5
  •  0
  •   Pavel Morshenyuk    14 年前

    空值为空,它不能等于或不等于某个值。 如果要检查值是否为空-请使用“is null”语句:

    select t.f1, t.f2
    from (select null f1, 'a' f2 from dual) t
    where t.f1 IS NULL
    

    如果要检查值是否相等-可以使用 COALESCE 可为空的列上的函数:

    select t.f1, t.f2
    from (select null f1, 'a' f2 from dual) t
    where COALESCE(t.f1, '')<>COALESCE(t.f2, '');