最近有人问我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()判断。
分享到:
相关推荐
3. **约束条件**:约束条件是对字段的附加规则,用以限制或验证字段中的数据。常见的约束有NOT NULL(不允许为空)、UNIQUE(唯一)、PRIMARY KEY(主键)、FOREIGN KEY(外键)等。虽然本节不关注约束条件,但它们...
如果既不指定NULL也不指定NOT NULL,列被认为指定了NULL 在 MySQL 中, 为一个 NOT NULL 字段设置 NULL 值 , 它并不会出错, MySQL 会自动将 NULL值转化为该字段的默认值, 那怕是你在表定义时没有...
我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时,该命令可能就无法正常工作。 为了处理这种情况,MySQL提供了三大运算符: IS NULL: 当列的值是 ...
MySQL 中 Null 值的处理和风险 在 MySQL 中, Null 值的存在可能会对数据库的性能和数据的准确性产生影响。在本期中,我们将讨论为什么不建议给 MySQL 设置 Null 值,并分析 Null 值对数据统计的影响。 1. Null 值...
在实际应用中,我们经常需要对数据进行自增长和时间戳记录,本文将详细介绍 MySQL 中的自增长和时间字段的使用。 自增长字段 在 MySQL 中,我们可以使用 auto_increment 属性来实现字段的自增长。例如,在创建用户...
对于NOT NULL字段的效率之所以比NULL高,是因为NULL值会增加存储空间和处理复杂性,同时也不参与索引,导致查询效率下降。在实际应用中,推荐在明确字段无需为空的情况下使用NOT NULL,以提高数据操作的效率。 其次...
删除字段前需谨慎,因为这将永久丢失字段中的所有数据。 4. **调整字段顺序**: 调整字段顺序虽然不常见,但在某些情况下可能有必要。这可以通过 `ALTER TABLE` 和 `CHANGE` 子句结合 `AFTER` 来完成: ```sql ...
理解这些知识点对于管理和维护MySQL数据库中的自增字段至关重要,可以帮助避免潜在的问题并优化数据存储效率。根据实际需求选择合适的存储引擎,以及正确处理自增字段的删除和初始化,能有效提升数据库的性能和管理...
在MySQL数据库中,查询空字段或非空字段是常见的操作,尤其在处理包含NULL值的数据时。NULL值在SQL中代表未知或者未定义,它与空字符串或零值有着本质的区别。本文将深入探讨如何使用`IS NULL`和`IS NOT NULL`条件来...
如果一个字段中没有指定 DEFAULT 修饰符,MySQL 会依据这个字段是 NULL 还是 NOT NULL 自动设置默认值。如果指定字段可以为 NULL,则 MySQL 为其设置默认值为 NULL。如果是 NOT NULL 字段,MySQL 对于数值类型插入 0...
-- 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=...
对于问题2,即NOT NULL字段的效率问题,由于NULL值需要额外存储和处理,所以它们在比较和索引时可能会影响性能。在执行查询时,使用"IS NOT NULL"条件通常比使用"<> ''"更准确,因为后者可能会误匹配非空但实际上是...
本篇文章将深入探讨在使用Hibernate存储MySQL表中的BLOB(Binary Large Object)字段时可能遇到的问题以及解决策略。 BLOB类型在MySQL中用于存储大量的二进制数据,如图片、视频、文档等。Hibernate作为Java中的ORM...
标题“行业-26 一行数据中的多个NULL字段值在磁盘上怎么存储”涉及到数据库管理系统中关于数据存储的问题,特别是当数据行中存在多个空(NULL)字段时的处理方式。在数据库设计中,NULL是一个特殊的值,表示某个字段...
NULL在MySQL中表示未知或未定义的值,与0或空字符串不同,NULL是一种特殊的标记,无法与其他值进行比较。 创建表时,列的定义需要指定列名、列类型以及可能的属性。例如,`content VARCHAR(20) NOT NULL`表示`...
然而,这些语句没有`WHERE`条件,这意味着`title`字段中的所有行都会被更新,这可能不是你想要的结果。通常,你应该指定一个条件来确保只更新满足特定条件的行,例如: ```sql UPDATE dede_archives SET title = ...
- UNIQUE:确保字段中的值是唯一的,但可以有NULL值。 - DEFAULT:设置字段的默认值,当插入新记录时,如果未提供该字段的值,系统会自动使用默认值。 - FOREIGN KEY:创建外键,建立与其他表之间的关系,实现...
前言 看了很多博客,也听过很多人说,包括我们公司的DBA...后来在官方文档中找到了说明,如果某列字段中包含null,确实是可以使用索引的,地址:https://dev.mysql.com/doc/refman/5.7/en/is-null-optimization.html。