大数跨境
0
0

SQL 语句中关于 NULL 的那些坑

SQL 语句中关于 NULL 的那些坑 数据分析与开发
2016-05-02
0
导读:今天在跟进公司内部测试平台线上问题的时候,发现一个忽略已久的问题。

(点击上方公众号,可快速关注)


来源:伯乐在线专栏作者 - debugtalk

链接:http://blog.jobbole.com/100413/

点击 → 了解如何加入专栏作者


问题描述


今天在跟进公司内部测试平台线上问题的时候,发现一个忽略已久的问题。


为了简化问题描述,将其进行了抽象。


有一张数据表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



专栏作者简介点击 → 加入专栏作者 )


debugtalk:专注于软件测试行业,享受在墙角安静地debug,也喜欢在博客上分享文字,个人微信公众号【debugtalk】。

 

打赏支持作者写出更多好文章,谢谢!




【今日微信账号推荐】

更多推荐请看值得关注的技术和设计公众号


其中推荐了包括技术设计极客 和 IT相亲相关的热门公众号。技术涵盖:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、数据库、运维、大数据、算法、IT职场等。点击《值得关注的技术和设计公众号》,发现精彩!



点击阅读原文,了解野狗

【声明】内容源于网络
0
0
数据分析与开发
「数据分析与开发」分享数据分析与开发相关技术文章、教程、工具
内容 2105
粉丝 0
数据分析与开发 「数据分析与开发」分享数据分析与开发相关技术文章、教程、工具
总阅读613
粉丝0
内容2.1k