`
丁林.tb
  • 浏览: 790588 次
  • 性别: 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
分享到:
评论

相关推荐

    NOT NULL 和NULL

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

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

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

    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值

    但是,当我们试图给的条件比较字段或列的值为NULL,它不能正常工作。 为了处理这种情况,MySQL提供了三大运算符 IS NULL: 此运算符返回true,当列的值是NULL。 IS NOT NULL: 运算符返回true,当列的值不是NULL。 ...

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

    本文介绍在MySQL中,面对值为空(NULL)的字段,应该如何查询。怎么判断一个字段的值为NULL或不为NULL,需要的朋友可以参考下

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

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

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

    要替换某一个字段中的部分内容,可以用update 语句: UPDATE 表名 SET 字段名= REPLACE( 替换前的字段值, ‘替换前关键字’, ‘替换后关键字’ ) WHERE 字段名 REGEXP “替换前的字段值”; 比如替换标题里面的产品...

    MySQL中使用SQL语句对字段进行重命名

    MySQL中,如何使用SQL语句来对表中某一个字段进行重命名呢?我们将使用alter table 这一SQL语句。 重命名字段的语法为:alter table &lt;表名&gt; change &lt;字段名&gt; &lt;字段新名称&gt; &lt;字段的类型&gt;。 现在我们来...

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

    今天小编就为大家分享一篇关于MySQL中可为空的字段设置为NULL还是NOT NULL,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

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

    NULL 博文链接:https://jaychang.iteye.com/blog/832693

    MySQL中文参考手册.chm

    8.4.4.6 NULL值操作 8.4.4.7 模式匹配 8.4.4.8 行计数 8.4.5 使用多个数据库表 8.5 获得数据库和表的信息 8.6 以批处理模式使用mysql 8.7 从"双胞项目"中查询 8.7.1 找出...

    小心陷阱!MySQL中处理Null时需注意两点

    但是如果将一个空值的数据插入到TimesTamp类型的字段中,空值就不一定为空。此时为出现什么情况呢(如下图)? 我先创建了一个表。在这个表中有两个字段:User_id(其数据类型是int)、Date(其数据类型是TimesTamp)。...

    MySQL NULL 值处理

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

    MySQL NULL 值处理实例详解

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

    详解mysql不等于null和等于null的写法

    1.表结构  2.表数据  3.查询teacher_name字段不能等于空并且也不能等于空字符 SELECT * FROM sys_teacher WHERE teacher_...到此这篇关于详解mysql不等于null和等于null的写法的文章就介绍到这了,更多相关mysql不

    MySQL 5.1中文手冊

    2.7. 在其它类Unix系统中安装MySQL 2.8. 使用源码分发版安装MySQL 2.8.1. 源码安装概述 2.8.2. 典型配置选项 2.8.3. 从开发源码树安装 2.8.4. 处理MySQL编译问题 2.8.5. MIT-pthreads注意事项 2.8.6. 在Windows下从...

    MySQL JSON类型字段操作

    1、Java 中动态扩展字段,会导致数据库表被锁,在MySQL 5.7.8版本之前,因为MySQL不能直接操作JSON类型数据,可以将一个字段设定成varchar类型,里面存放JSON格式数据,这样在需要扩展字段时,不需要修改表结构;...

    MySQL null与not null和null与空值的区别详解

    相信很多用了MySQL很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 我字段类型是not null,为什么我可以插入空值 为毛not null的效率比null高 判断字段不为空的时候,到底... mysql中的NULL其实

    Mysql中批量替换某个字段的部分数据(推荐)

    example: update table set url= replace(url, 'aaa', 'bbb') 【将url字段中的aaa批量更改为bbb】 update table set url= REPLACE (url,'3','1.png') where 条件; 2.常规条件修改: update table set column='' ...

Global site tag (gtag.js) - Google Analytics