`
丁林.tb
  • 浏览: 797242 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

MySQL中NULL字段的比较问题

阅读更多

最近有人问我MySQL中一个字段不论=NULL还是<>NULL都匹配不了数据,是在框架层实现的还是在存储引擎层实现的,我说你看看如果InnoDB表和MyISAM表都有这个现象,那就比较可能是在框架层

当然这个答案跟没有回答一样,我们可以从代码上看看具体的实现部分。

 

1、              现象描述

表结构

CREATE TABLE `t` (

  `c` char(32) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=gbk

插入两行数据

insert into t (c) values('a'),(null);

查询

mysql> select * from t where c=null;

Empty set (0.00 sec)

 

mysql> select * from t where c<>null;

Empty set (0.00 sec)

 

mysql> select * from t where c is not null;

+------+

| c    |

+------+

| a    |

+------+

1 row in set (0.00 sec)

说明:从上面的三个查询可以看出,使用=null<>null都无法返回数据,只能通过isis not 来比较。

 

2、代码相关

      我们知道大概的流程,是引擎返回索引过滤后的结果,在框架层再依次判断记录是否符合条件。判断条件是否满足是在函数evaluate_join_record (sql_select.cc)中。

if (select_cond) 
{
  select_cond_result= test(select_cond->val_int()); /* check for errors evaluating the condition */

  if (join->thd->is_error())
    return NESTED_LOOP_ERROR;
}

if (!select_cond || select_cond_result)
 { ... } 

 

 

 

 

第三行的select_cond->val_int(),就是判断where的条件是否相同。其中select_cond的类型Item是一个虚类。我们从val_int()的函数注释中看到这样一句话“In case of NULL value return 0 and set null_value flag to TRUE.”,确认了这个是在框架层作的,而且是有意为之。

 

一路追查到这个函数int Arg_comparator::compare_string (sql/item_cmpfunc.cc),这个函数是用语判断两个字符串是否相同。

int Arg_comparator::compare_string()

{

  String *res1,*res2;

  if ((res1= (*a)->val_str(&value1)))

  {

    if ((res2= (*b)->val_str(&value2)))

    {   

      if (set_null)

        owner->nullvalue= 0;

      return sortcmp(res1,res2,cmp_collation.collation);

    }   

  }

  if (set_null)

    owner->nullvalue= 1;

  return -1;

}

 

函数返回值为0时表示相同,否则不同。

其中a是左值,b是右值。即如果输入的是 where ‘i’=c, a的值是’i’。从第4行和第6行的两个if看到,当ab中有一个是null的时候,不进入sortcmp,而是直接return -1

 

3、验证修改

       声明:这个只是为了验证结论修改,纯属练手,实际上现有的策略并没有问题。

 

int Arg_comparator::compare_string()   
{   
  String *res1,*res2;   
  res1= (*a)->val_str(&value1);   
  res2= (*b)->val_str(&value1);   
  if (!res1 && !res2)   
  {   
    return 0;   
  }   
  else if ((!res1 && res2) || (res1 && !res2))    
  {   
    return 1;   
  }   
  else  
  {   
    return sortcmp(res1,res2,cmp_collation.collation);   
  }   
}  

  

 

 

重新编译后执行效果如下

mysql> select * from t where c=null;

+--------------+

| c           |

+--------------+

| NULL    |

+--------------+

1 row in set (0.00 sec)

 

mysql> select * from t where c<>null;

+--------------+

| c        |

+--------------+

| a        |

+--------------+

1 row in set (0.00 sec)

 

 记得改回去。。。 ^_^

 

4、相关说明

a) Arg_comparator::compare_string() 这个函数只用于定义两个char[]的判断规则,因此修改后的执行程序中,非字符串字段判断仍为原来的规则,即=null<>null都认为不匹配。

b) 标准判断是否为null的用法是 where c is nullis not null。此时使用的判断函数为Item_func_isnull::val_int()Item_func_isnotnull::val_int() 这两个函数比较简单,直接用args[0]->is_null()判断

 

 

2
0
分享到:
评论

相关推荐

    MySQL数据表添加字段

    3. **约束条件**:约束条件是对字段的附加规则,用以限制或验证字段中的数据。常见的约束有NOT NULL(不允许为空)、UNIQUE(唯一)、PRIMARY KEY(主键)、FOREIGN KEY(外键)等。虽然本节不关注约束条件,但它们...

    NOT NULL 和NULL

    如果既不指定NULL也不指定NOT NULL,列被认为指定了NULL 在 MySQL 中, 为一个 NOT NULL 字段设置 NULL 值 , 它并不会出错, MySQL 会自动将 NULL值转化为该字段的默认值, 那怕是你在表定义时没有...

    Mysql实现null值排在最前/最后的方法示例

    我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。 为了处理这种情况,MySQL提供了三大运算符: IS NULL: 当列的值是 ...

    为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》.doc

    MySQL 中 Null 值的处理和风险 在 MySQL 中, Null 值的存在可能会对数据库的性能和数据的准确性产生影响。在本期中,我们将讨论为什么不建议给 MySQL 设置 Null 值,并分析 Null 值对数据统计的影响。 1. Null 值...

    mysql 自增长 时间字段

    在实际应用中,我们经常需要对数据进行自增长和时间戳记录,本文将详细介绍 MySQL 中的自增长和时间字段的使用。 自增长字段 在 MySQL 中,我们可以使用 auto_increment 属性来实现字段的自增长。例如,在创建用户...

    MySQL SQL高级特性 字段约束-索引-视图-外键学习实践

    对于NOT NULL字段的效率之所以比NULL高,是因为NULL值会增加存储空间和处理复杂性,同时也不参与索引,导致查询效率下降。在实际应用中,推荐在明确字段无需为空的情况下使用NOT NULL,以提高数据操作的效率。 其次...

    mysql中添加字段insert

    删除字段前需谨慎,因为这将永久丢失字段中的所有数据。 4. **调整字段顺序**: 调整字段顺序虽然不常见,但在某些情况下可能有必要。这可以通过 `ALTER TABLE` 和 `CHANGE` 子句结合 `AFTER` 来完成: ```sql ...

    mysql自增字段重排 mysql删除表后自增字段从1开始.pdf

    理解这些知识点对于管理和维护MySQL数据库中的自增字段至关重要,可以帮助避免潜在的问题并优化数据存储效率。根据实际需求选择合适的存储引擎,以及正确处理自增字段的删除和初始化,能有效提升数据库的性能和管理...

    MySQL查询空字段或非空字段(is null和not null)

    在MySQL数据库中,查询空字段或非空字段是常见的操作,尤其在处理包含NULL值的数据时。NULL值在SQL中代表未知或者未定义,它与空字符串或零值有着本质的区别。本文将深入探讨如何使用`IS NULL`和`IS NOT NULL`条件来...

    MySQL 字段约束 mysql学习笔记

    如果一个字段中没有指定 DEFAULT 修饰符,MySQL 会依据这个字段是 NULL 还是 NOT NULL 自动设置默认值。如果指定字段可以为 NULL,则 MySQL 为其设置默认值为 NULL。如果是 NOT NULL 字段,MySQL 对于数值类型插入 0...

    mysql列转为非固定字段

    -- MySQL 行转列 非固定列 2009-4-25 by kim -- CREATE TABLE `expense_log` ( -- `EXPENSE_ID` INT(10) DEFAULT NULL, -- `USER_ID` VARCHAR(45) DEFAULT NULL, -- `TOTAL` INT(11) DEFAULT NULL -- ) ENGINE=...

    MySQL中可为空的字段设置为NULL还是NOT NULL

    对于问题2,即NOT NULL字段的效率问题,由于NULL值需要额外存储和处理,所以它们在比较和索引时可能会影响性能。在执行查询时,使用"IS NOT NULL"条件通常比使用"&lt;&gt; ''"更准确,因为后者可能会误匹配非空但实际上是...

    使用Hibernaet存储MYSQL表中BLOB字段的问题

    本篇文章将深入探讨在使用Hibernate存储MySQL表中的BLOB(Binary Large Object)字段时可能遇到的问题以及解决策略。 BLOB类型在MySQL中用于存储大量的二进制数据,如图片、视频、文档等。Hibernate作为Java中的ORM...

    行业-26 一行数据中的多个NULL字段值在磁盘上怎么存储.rar

    标题“行业-26 一行数据中的多个NULL字段值在磁盘上怎么存储”涉及到数据库管理系统中关于数据存储的问题,特别是当数据行中存在多个空(NULL)字段时的处理方式。在数据库设计中,NULL是一个特殊的值,表示某个字段...

    MySql字段类型

    NULL在MySQL中表示未知或未定义的值,与0或空字符串不同,NULL是一种特殊的标记,无法与其他值进行比较。 创建表时,列的定义需要指定列名、列类型以及可能的属性。例如,`content VARCHAR(20) NOT NULL`表示`...

    MySQL 替换某字段内部分内容的UPDATE语句

    然而,这些语句没有`WHERE`条件,这意味着`title`字段中的所有行都会被更新,这可能不是你想要的结果。通常,你应该指定一个条件来确保只更新满足特定条件的行,例如: ```sql UPDATE dede_archives SET title = ...

    mysql添加字段.docx

    - UNIQUE:确保字段中的值是唯一的,但可以有NULL值。 - DEFAULT:设置字段的默认值,当插入新记录时,如果未提供该字段的值,系统会自动使用默认值。 - FOREIGN KEY:创建外键,建立与其他表之间的关系,实现...

    MySQL中NULL对索引的影响深入讲解

    前言 看了很多博客,也听过很多人说,包括我们公司的DBA...后来在官方文档中找到了说明,如果某列字段中包含null,确实是可以使用索引的,地址:https://dev.mysql.com/doc/refman/5.7/en/is-null-optimization.html。

Global site tag (gtag.js) - Google Analytics