最近有人问我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都无法返回数据,只能通过is或is 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看到,当a和b中有一个是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 null和is not null。此时使用的判断函数为Item_func_isnull::val_int()和Item_func_isnotnull::val_int(),这两个函数比较简单,直接用args[0]->is_null()判断。

2

0

分享到:

2010-12-06 21:21

浏览 10953

分类:数据库

评论

mysql c null_MySQL中NULL字段的比较问题相关推荐

  1. 如何更新mysql数据库字段_如何使用MySQL一个表中的字段更新另一个表中字段

    1,修改1列 update student s, city c set s.city_name = c.name where s.city_code = c.code; 2,修改多个列 update ...

  2. mysql高效查出重复的手机号_Mysql必读MySQL大表中重复字段的高效率查询方法

    <MysqL必读MysqL大表中重复字段的高效率查询方法>要点: 本文介绍了MysqL必读MysqL大表中重复字段的高效率查询方法,希望对您有用.如果有疑问,可以联系我们.MysqL大表重 ...

  3. mysql修改表中某个字段的默认值

    Mysql中用SQL增加.删除字段,修改字段名.字段类型.注释,调整字段顺序总结 在网站重构中,通常会进行数据结构的修改,所以添加,删除,增加mysql表的字段是难免的,有时为了方便,还会增加修改表或 ...

  4. mysql:分组中某字段最大值的查询结果

    最近在用一款组态软件,涉及到sql查询来得出数据集.需要在一定的限制下,得出想要的查询结果.某些查询的方法整理一下. 这次记录的是分组中某字段最大值的查询结果: 比如:从一张记录装置缺陷的表中,查询出 ...

  5. mysql的字段空格是null_MySQL中NULL与空字符串 空格问题

    一些刚刚接触MySQL的孩子,经常会错误的认为NULL与空字符串' '是相同的.这看似是一件不重要的事情,但是在MySQL中,这两者是完全不同的.NULL是指没有值,而''则表示值是存在的,只不过是个 ...

  6. mysql联合索引排序_对mysql联合索引中的字段进行合理排序

    在MySQL的where条件中,有时会用到很多的条件,通常为了加快速度会把这些字段放到联合索引中,可以更快的提高搜索速度: 但是对联合索引中字段顺序的合理排序,便更能提高速度 例子:select * ...

  7. mysql取最大一条数据,mysql取出表中,某字段值最大的一条纪录,sql语句

    一个为交易表,有唯一id,别名trade_id 一个为交易状态详情表,记录trade_id的多个状态. 进行了两个表查询.查询某个trade_id的交易情况及最新状态. 直接粘贴此sql,执行即知. ...

  8. mysql查询数据库中所有字段的属性

    大型项目中数据库中有成百上千张表,想要统计数据库中相同的字段名,不同的长度或类型,所有的字段属性. 利用简单的SQL帮助我们进行统计. 1.查询数据库中某个库所有字段的属性(指定数据库库名),若想查询 ...

  9. mysql如何查询表中所有字段的名字

    select COLUMN_NAME,column_comment from INFORMATION_SCHEMA.Columns where table_name='表名' and table_sc ...

最新文章

  1. Matlab使用笔记
  2. 利用fnd_conc_global.set_req_globals设置子请求的Parent Request ID
  3. C#集合类(HashTable, Dictionary, ArrayList)与HashTable线程安全
  4. LeetCode打卡 52八皇后Ⅱ53最大子序和54螺旋矩阵
  5. Hardcoded string , should use @string resource警告 Tag start is not closed
  6. 哈利波特检索_语料库ing说: 难怪哈利波特与混血王子那么好看
  7. 非苹果PC安装MacOS
  8. C# 日志管理框架:Common.Logging和log4net
  9. 支付宝的一些小问题,注意事项等等,等用得时候在来写写
  10. C++ | Qt 获取局域网中存在的主机(IP以及主机名)
  11. android 圆点指示器,ViewPager加上小圆点指示器效果
  12. java sun包无法引用_关于java包的问题,自己创建一个包,里面放了源文件,却包外无法引用:具体见问题补充...
  13. ubuntu linux 从入门到精通.pdf,UBUNTU LINUX从入门到精通(附DVD)
  14. 微信公众号服务号如何在线给粉丝发送模板消息
  15. C语言求解黎曼 函数非平凡零点,51、黎曼函数的“非平凡零点 (1/2)z”是什么玩意?...
  16. 你听过“易语言”吗?
  17. 常见的厂家的加固方式做一下总结
  18. 使用Anki批量导入选择题实录
  19. 一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之间混乱关系(史上最全)
  20. vue学习笔记(一)

热门文章

  1. IDEA导入项目笔记二
  2. python把csv做成柱状图_用Python的Matplotlib模块实现CSV数据格式的可视化
  3. oracle升级后报 06502,Oracle数据库升级后报ORA-00704和ORA-39700错误
  4. JS(ES6)、Vue.js、node.js
  5. 调试 Dockerfile - 每天5分钟玩转 Docker 容器技术(15)
  6. 细说IIS异常日志 — 你必须知道的功能
  7. Linux软件间的依赖关系(转)
  8. Mysql笔记之 -- replace()实现mysql 替换字符串
  9. POST方式提交乱码解决
  10. Android 音频均衡器,可通过拖动调节音频EQ