暂无图片
mysql 明明设置了not null default,为什么用where name is null还能查到null值
我来答
分享
czxin788
2022-07-01
mysql 明明设置了not null default,为什么用where name is null还能查到null值

mysql 明明设置了not null default,为什么用where name is null还能查到数据null值

见下面的例子

mysql> create table t (id int primary key, name varchar(20) not null default 'kong');
Query OK, 0 rows affected (0.56 sec)

mysql> insert into t values (1,'zhangsan');
Query OK, 1 row affected (0.10 sec)

mysql>  insert into t values (2,'lisi');
Query OK, 1 row affected (0.11 sec)

mysql>  select * from t;
+----+----------+
| id | name     |
+----+----------+
|  1 | zhangsan |
|  2 | lisi     |
+----+----------+
2 rows in set (0.00 sec)

mysql> alter table t add column create_time datetime not null default '0000-00-00 00:00:00';
Query OK, 0 rows affected (0.39 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into t values ('4','wangwu','2022-07-01 10:00:00');
Query OK, 1 row affected (0.11 sec)

mysql> select * from t;
+----+----------+---------------------+
| id | name     | create_time         |
+----+----------+---------------------+
|  1 | zhangsan | 0000-00-00 00:00:00 |
|  2 | lisi     | 0000-00-00 00:00:00 |
|  4 | wangwu   | 2022-07-01 10:00:00 |
+----+----------+---------------------+
3 rows in set (0.00 sec)

mysql> select * from t  where create_time is null;
+----+----------+---------------------+
| id | name     | create_time         |
+----+----------+---------------------+
|  1 | zhangsan | 0000-00-00 00:00:00 |
|  2 | lisi     | 0000-00-00 00:00:00 |
+----+----------+---------------------+
2 rows in set (0.00 sec)
复制


很不解呀,明明create_time列有值0000-00-00 00:00:00,但是select * from t where create_time is null 却认为有null值。

请问这是怎么回事



我来答
添加附件
收藏
分享
问题补充
9条回答
默认
最新
严少安
暂无图片

当前 sql_mode 是什么?
select @@sql_mode;

可以用,
alter table t add column create_time datetime not null default CURRENT_TIMESTAMP;

暂无图片 评论
暂无图片 有用 1
打赏 0
暂无图片
chengang

官方文档有这样一句话。
MySQL permits you to store a “zero” value of ‘0000-00-00’ as a “dummy date.” In some cases, this is more convenient than using NULL values, and uses less data and index space. To disallow ‘0000-00-00’, enable the NO_ZERO_DATE mode.

“Zero” date or time values used through Connector/ODBC are converted automatically to NULL because ODBC cannot handle such values.

https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html

暂无图片 评论
暂无图片 有用 2
打赏 0
czxin788

mysql> show variables like '%sql_mode%';
+---------------+-------------------------------------------------------------------------------------------+
| Variable_name | Value |
+---------------+-------------------------------------------------------------------------------------------+
| sql_mode | STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+---------------+-------------------------------------------------------------------------------------------+
1 row in set (0.08 sec)

暂无图片 评论
暂无图片 有用 0
打赏 0
czxin788

意思是说,mysql会强制把zero date转为null,因为odbc不能处理zero date,会吧zero date自动转换为null

暂无图片 评论
暂无图片 有用 0
打赏 0
严少安
2022-07-01
datetime 类型的取值范围是,The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'. 而 '0000-00-00 00:00:00' 是非法数值。
严少安
2022-07-01
而非法数值就会判定为null
czxin788

看了一下执行计划

mysql> desc select * from t  where create_time is null \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 5
     filtered: 20.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)
复制


mysql> show warnings;
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                          |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `czx`.`t`.`id` AS `id`,`czx`.`t`.`name` AS `name`,`czx`.`t`.`create_time` AS `create_time` from `czx`.`t` where (`czx`.`t`.`create_time` = '0000-00-00 00:00:00') |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
复制


可以看到,mysql把where create_time is null ,偷偷的转换成了,where create_time = '0000-00-00 00:00:00'。

暂无图片 评论
暂无图片 有用 0
打赏 0
严少安
2022-07-01
您好,顺便问下,您这具体是哪个版本?
czxin788

mysql 5.7.22

暂无图片 评论
暂无图片 有用 0
打赏 0
严少安
暂无图片
暂无图片 评论
暂无图片 有用 0
打赏 0
czxin788

谢谢,github里面说的没有看明白,是说这是个bug,现在已经解决了吗

暂无图片 评论
暂无图片 有用 0
打赏 0
严少安
2022-07-01
就是解释了下'0000-00-00 00:00:00' 和 sql_mode的关系,很早之前的事情了。 如果你的sql_mode 更严格,你的那条alter就会执行失败。
薛晓刚

0000这种被称为错误数据。我们多次从MySQL导入到Oracle中验证过,这种属于不合法。从8版本以后也杜绝了这种。

暂无图片 评论
暂无图片 有用 0
打赏 0
回答交流
Markdown


请输入正文
提交
相关推荐
MySQL下载后只能用命令提示符操作吗?
回答 2
有msyqlworkbench,还有navicat,都是数据库的图形操作工具
如何加强MySQL安全,请给出可行的具体措施?
回答 5
已采纳
1、删除数据库不使用的默认用户2、配置相应的权限(包括远程连接)3、不可在命令行界面下输入数据库密码4、定期修改密码与加强密码的复杂度
以下描述中对mysql里并行复制描述正确的有哪些?
回答 1
已采纳
全选ABCD
MySQL 8.0.31 怎么修改特定数据库下地function的definer?
回答 4
学习
MySQL 以下SQL如何优化?
回答 3
没有表信息,没有索引信息,没有执行计划从语句上看,我觉得可以有两点可以优化。1、第一个with其实可以直接使用innerjoin(但我估计优化器已给你优化成了innerjoin)2、建一个tochar
关于从库relaylog中的时间戳,在io线程有延时的情况下的疑问
回答 1
这延时有点大,互换存储吧
在生产环境下,MySQL采用什么方式安装,一般安装哪个版本?
回答 3
生产环境一般采用二进制解压方式来安装,而不是编译安装,编译安装的复杂度高且没有什么优势,基本上不会采用编译或者rpm包的方式安装。二进制解压方式比较灵活,配置也更方便。现在强烈建议采用8.0的最新版本
MySQL 随机取字符,有时候获取到空值,怎么样才避免呢? 保证字符串是多行排?
回答 3
路过
银河麒麟通过docker 安装MySQL报错:mysqld failed..., 这是什么原因导致的?
回答 3
我这边有现成的MySQLDoeckerfile文件,要的联系!
在mysql中,有哪些优化方法可用?
回答 3
官方文档专门有一章来讲mysql优化…这有篇相关的翻译https://cloud.tencent.com/developer/article/2156162