SQL 语句中关于 NULL 的那些坑
问题描述
今天在跟进公司内部测试平台线上问题的时候,发现一个忽略已久的问题。
为了简化问题描述,将其进行了抽象。
有一张数据表qms_branch,里面包含了一批形式如下所示的数据:
id | name | types |
---|---|---|
1 | dashboard_trunk | dashboard |
2 | monkey_trunk | monkey |
3 | dashboard_projects_10_9_9 | dashboard |
4 | performance_trunk | |
5 | performance_projects_10_9_8 | performance |
在系统的某个页面中,需要展示出所有dashboard类型以外的分支,于是就采用如下方式进行查询(Rails)。
branches = Qms::Branch.where("types!='dashboard'")
这个方式有问题么?
之前我是觉得没什么问题。但是在代码上线后,实际使用时发现部分分支没有加载出来,这就包括了performance_trunk分支。
然后就是问题定位,到MySQL的控制台采用SQL语句进行查询:
SELECT * FROM qms_branch WHERE types != 'dashboard'
发现在查询结果中的确没有包含performance_trunk分支。
这是什么原因呢?为什么在第4条数据中,types属性的值明明就不是dashboard,但是采用types!='dashboard'就无法查询得到结果呢?
原因追溯
查看数据表qms_branch的结构,看到types字段的属性为:DEFAULT NULL。
经过查询资料,在w3schools上找到了答案。
NULL is used as a placeholder for unknown or inapplicable values, it is treated differently from other values.
It is not possible to test for NULL values with comparison operators, such as =, <, or <>. We will have to use the IS NULL and IS NOT NULL operators instead.
也就是说,在SQL中,NULL并不能采用!=与数值进行比较,若要进行比较,我们只能采用IS NULL或IS NOT NULL。
于是,我们将SQL语句改为如下形式:
SELECT * FROM qms_branch WHERE types IS NULL or types != 'dashboard'
再次查询时,结果集就包含performance_trunk分支了。
问题延伸
通过上面例子,我们知道在对NULL进行判断处理时,只能采用IS NULL或IS NOT NULL,而不能采用=, <, <>, !=这些操作符。
那除此之外,还有别的可能存在的坑么?
再看一个例子:
有一张数据表table_foo,其中有一个字段value_field,我们想从这张表中筛选出所有value_field为’value1’,’value2’或NULL的记录。
那么,我们采用IN操作符,通过如下SQL语句进行查询。
SELECT * FROM table_foo WHERE value_field IN ('value1', 'value2', NULL)
这会存在问题么?我们并没有采用=, <, <>, !=对NULL进行比较哦。
答案是同样存在问题!
因为在SQL中,IN语句会被转换为多个=语句。例如,上面例子中的SQL在执行时就会被转换为如下SQL语句:
SELECT * FROM table_foo WHERE value_field = 'value1' OR value_field = 'value2' OR value_field = NULL
而这个时候,执行value_field = NULL时就会出现问题了。
正确的做法应该是将NULL相关的判断独立出来,如下SQL才是正确的写法。
SELECT * FROM table_foo WHERE value_field IN ('value1', 'value2') OR value_field IS NULL
SQL 语句中关于 NULL 的那些坑的更多相关文章
- SQL语句中=null和is null
平时经常会遇到这两种写法:IS NOT NULL与!=NULL.也经常会遇到数据库有符合条件!=NULL的数据,但是返回为空集合.实际上,是由于对二者使用区别理解不透彻. 默认情况下,推荐使用 IS ...
- 关于SQL语句中SUM函数返回NULL的解决办法
SUM 是SQL语句中的标准求和函数,如果没有符合条件的记录,那么SUM函数会返回NULL. 但多数情况下,我们希望如果没有符合条件记录的情况下,我们希望它返回0,而不是NULL,那么我们可以使用例如 ...
- sql 语句中count()有条件的时候为什么要加上or null
参考:https://blog.csdn.net/qq_32719287/article/details/79513164 1.sql 语句中count()有条件的时候为什么要加上or null. 如 ...
- mybatis sql语句中 in() 长度为0或null的情况
mybatis sql语句中 in() 长度为0或null的情况 比如: select * from A where colName IN <foreach collection="m ...
- MyBatis 动态 SQL 语句中出现 '<' 的问题
问题描述 映射接口方法如下: /** * 根据姓名和年龄查询用户信息 * @param name 姓名 * @param user 获取年龄 * @return */ public List<U ...
- SQL语句中count(1)count(*)count(字段)用法的区别
SQL语句中count(1)count(*)count(字段)用法的区别 在SQL语句中count函数是最常用的函数之一,count函数是用来统计表中记录数的一个函数, 一. count(1)和cou ...
- 向已写好的多行插入sql语句中添加字段和值
#region 添加支款方式--向已写好的多行插入sql语句中添加字段和值 public int A_ZhifuFS(int diqu) { ; string strData = @"SEL ...
- SQL点滴35—SQL语句中的exists
原文:SQL点滴35-SQL语句中的exists 比如在Northwind数据库中有一个查询为 SELECT c.CustomerId,CompanyName FROM Customers c WHE ...
- SQL点滴31—SQL语句中@@IDENTITY和@@ROWCOUNT区别
原文:SQL点滴31-SQL语句中@@IDENTITY和@@ROWCOUNT区别 SQL语句中@@IDENTITY和@@ROWCOUNT区别 在一条 INSERT.SELECT INTO 或大容量复制 ...
随机推荐
- LeetCode 572. 另一个树的子树(Subtree of Another Tree) 40
572. 另一个树的子树 572. Subtree of Another Tree 题目描述 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树.s 的一个子树包括 ...
- SQL——IN操作符
一.IN操作符基本用法 IN操作符用于在WHERE字句中规定多个值. 语法格式如下: SELECT 列名1,列名2... FROM 表名 WHERE 列名 IN(值1,值2...); 示例studen ...
- Find the median(线段树+离散化)(2019牛客暑期多校训练营(第七场))
题目出处:Find the median 示例: 输入: 53 1 4 1 5 92 7 1 8 2 9 输出:3 4 5 4 5 说明:L = [3, 2 ,4, 1, 7],R = [4, 8, ...
- Ubuntu遇到apt-get update报错:"E: Could not get lock /var/lib/apt/lists/lock"
sudo apt-get update报错:"E: Could not get lock /var/lib/apt/lists/lock" 出现此问题的原因可能是有另外一个程序在运 ...
- (转)Nginx+rtmp+ffmpeg搭建流媒体服务器
(1)下载第三方扩展模块nginx-rtmp-module # mkdir module && cd module //创建一个存放模块的目录 # wget https://githu ...
- 物流管理系统(SSM+vue+shiro)【前后台】
一.简单介绍项目 该项目是属于毕业设计项目之一,有前台的用户下单.有司机进行接单.有管理员进行操作后台,直接进入主题 毕设.定制开发 联系QQ:761273133 登录主页: 手机号码+验证码登录 或 ...
- JSP 9大隐式对象和四个作用域的范围
Java中 九大隐式对象说明 输入/输出对象: request response out 作用域通信对象: session application pageContext Servlet ...
- NIO开发Http服务器(1):项目下载、打包和部署
最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...
- 【洛谷 P4248】 [AHOI2013]差异(后缀自动机)
题目链接 \[ans=\sum_{1<=i<j<=n}len(T_i)+len(T_j)-2*lcp(T_i,T_j)\] 观察这个式子可以发现,前面两个\(len\)是常数,后面的 ...
- OO——JML作业总结
目录 第三单元博客作业 JML语言理论基础 1.注释结构 2.JML表达式 3.方法规格 4.类型规格 应用工具链 JMLUnitNG使用实例 作业架构设计 第一次作业 第二次作业 第三次作业 BUG ...