最近有人问我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()判断。
分享到:
相关推荐
如果既不指定NULL也不指定NOT NULL,列被认为指定了NULL 在 MySQL 中, 为一个 NOT NULL 字段设置 NULL 值 , 它并不会出错, MySQL 会自动将 NULL值转化为该字段的默认值, 那怕是你在表定义时没有...
我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。 为了处理这种情况,MySQL提供了三大运算符: IS NULL: 当列的值是 ...
-- 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=...
但是,当我们试图给的条件比较字段或列的值为NULL,它不能正常工作。 为了处理这种情况,MySQL提供了三大运算符 IS NULL: 此运算符返回true,当列的值是NULL。 IS NOT NULL: 运算符返回true,当列的值不是NULL。 ...
本文介绍在MySQL中,面对值为空(NULL)的字段,应该如何查询。怎么判断一个字段的值为NULL或不为NULL,需要的朋友可以参考下
前言 看了很多博客,也听过很多人说,包括我们公司的DBA...后来在官方文档中找到了说明,如果某列字段中包含null,确实是可以使用索引的,地址:https://dev.mysql.com/doc/refman/5.7/en/is-null-optimization.html。
要替换某一个字段中的部分内容,可以用update 语句: UPDATE 表名 SET 字段名= REPLACE( 替换前的字段值, ‘替换前关键字’, ‘替换后关键字’ ) WHERE 字段名 REGEXP “替换前的字段值”; 比如替换标题里面的产品...
MySQL中,如何使用SQL语句来对表中某一个字段进行重命名呢?我们将使用alter table 这一SQL语句。 重命名字段的语法为:alter table <表名> change <字段名> <字段新名称> <字段的类型>。 现在我们来...
今天小编就为大家分享一篇关于MySQL中可为空的字段设置为NULL还是NOT NULL,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
NULL 博文链接:https://jaychang.iteye.com/blog/832693
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 找出...
但是如果将一个空值的数据插入到TimesTamp类型的字段中,空值就不一定为空。此时为出现什么情况呢(如下图)? 我先创建了一个表。在这个表中有两个字段:User_id(其数据类型是int)、Date(其数据类型是TimesTamp)。...
我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。 为了处理这种情况,MySQL提供了三大运算符: IS NULL: 当列的值是 ...
我们已经知道MySQL使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。 为了处理这种情况,MySQL提供了三大运算符: IS NULL: 当列的值是NULL,...
1.表结构 2.表数据 3.查询teacher_name字段不能等于空并且也不能等于空字符 SELECT * FROM sys_teacher WHERE teacher_...到此这篇关于详解mysql不等于null和等于null的写法的文章就介绍到这了,更多相关mysql不
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下从...
1、Java 中动态扩展字段,会导致数据库表被锁,在MySQL 5.7.8版本之前,因为MySQL不能直接操作JSON类型数据,可以将一个字段设定成varchar类型,里面存放JSON格式数据,这样在需要扩展字段时,不需要修改表结构;...
相信很多用了MySQL很久的人,对这两个字段属性的概念还不是很清楚,一般会有以下疑问: 我字段类型是not null,为什么我可以插入空值 为毛not null的效率比null高 判断字段不为空的时候,到底... mysql中的NULL其实
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='' ...