一、提出问题

  不可避免地,我们都数据库总有一些字段是没有值的。不管是插入一个不完整的行,还是有些列可以合法地拥有一些无效值。SQL 支持一个特殊的空值,就是NULL。

  在很多时候,NULL值导致我们的程序出现报错的现象,于是很多人就开始拒绝NULL值,想各种各样的方法来避免使用NULL值,但是很遗憾,NULL值恰恰就是满足我们的需要用于表示空值的。

  空值经常存在于我们的数据库当中:

  •   例如一个在职员工的离职时间。
  •   例如一辆电力驱动的车的燃油消耗比。

二、反模式

  很多人对于NULL值感觉到恐惧,原因在于不知道什么时候就会因为一个NULL冒出一个报错。实际上都是由于对NULL值的理解有误引起的。很多人将NULL值当做一个0、False、空字符串来理解。实际上SQL将NULL当做一个特殊的值,并不同于0、false、空字符串。

  实际上对NULL值最好的理解是“不知道”。用“不知道”可以正确理解与NULL值的运算,如"+","-",AND,OR,NOT等。

  我们来看看容易出错的地方。

  首先,我们建一张表如下:

  

  在里面添加几条数据:

  

  注意里面的NULL值。

  我们,来看看如下SQL语句的结果:

  

  以上可以理解为:不知道+10=不知道

  

  留意到上面的数据少了一条,Age为NULL的那一条,原因在于NOT (NULL)的值并不为True也并不为False而是NULL。

  以上的例子还有很多,于是就出现了很多人引用一个普通的值来代替NULL值,例如"无效"、"未知"或者-1。假设我们使用的是-1,虽然我们在使用

SELECT * FROM Person WHERE Age <> -1

  作为查询条件,看起来没什么问题,但是这时候当我们使用SUM、AVG等聚合函数的时候就会导致计算结果出错。

  使用NULL并不是反模式,反模式是将NULL作为一个普通值处理或者使用一个普通的值来取代NULL的作用。

三、解决方案 - 将NULL视为特殊值

  下面先列举一些程序员运用NULL运算时期望得到的结果与实际结果。

  1、在标量表达式中使用NULL

表达式 期望值 实际值 原因
NULL=0 TRUE NULL NULL不是0
NULL=12345 FALSE NULL 未指定值不知道是否等于所给值
NULL<>12345 TRUE NULL 未指定值也不知道一定不等于所给值
NULL+12345 12345 NULL NULL不是0
NULL||'string' 'string' NULL NULL不是空字符串
NULL=NULL TRUE NULL 两个都不知道,鬼知道你等不等
NULL!=NULL FALSE NULL 两个都不知道,贵知道你等不等

  2、在布尔表达式中使用NULL

表达式 期望值 实际值 原因
NULL AND TRUE FALSE NULL NULL不是FALSE
NULL AND FALSE FALSE FALSE FALSE AND 什么都是FALSE
NULL OR FALSE FALSE NULL NULL不是FALSE
NULL OR TRUE TRUE TRUE TRUE OR 什么都是TRUE
NOT (NULL) TRUE NULL NULL 不是FALSE

  3、检索NULL值

  由于=NULL或者不等于NULL操作在对NULL进行比较时都是返回NULL,因此在检索NULL的时候,要用写特别操作:

  IS NULL 和 IS NOT NULL

  对于上面的例子,如果我们希望检索NULL,可以这样写:

  

  4、声明NOT NULL列

  如果NULL会破坏程序结构或者NULL本身就是毫无意义的,那么最好就在定义列时加上NOT NULL约束。让数据库来帮你确保约束的实行比自己写代码可靠得多。

  有人建议为每一列都定义一个DEFAULT值,这样一来当在执行插入操作时,即使省略了某一列,也能获得一个非NULL值。这样的建议也并不是通用的。就假设有一个年龄列,设置了一个Default值为0,那么使用AVG聚合函数的时候结算的是错误的结果。NULL值是不被纳入AVG的计算范畴之内的,而0会被计算。

  

  如对于上表:

  

  而,如果我们将最后两行设置为0,那么AVG的结果将是:

  

  5、动态默认值

  动态默认值这个东西的意思是,当我们的查询碰到一个NULL值的时候,我们希望它返回一个非NULL的默认值,已不至于计算出错。

  比如 姓 + NULL + 名返回的是NULL。

  因此,我们不希望中间返回NULL,而是''空字符串。这样计算才正常。

  大部分数据库都提供了一个COALESCE函数实现这个功能,来看SQLServer中的示例:

  我们将第一行的姓名置NULL

  

 
 

查询反模式 - 正视NULL值的更多相关文章

  1. 针对多条件查询,应对 url 无用 null 值现象处理

    多条件查询 应对 url 无用 null 值现象 处理例如:http://xxoo.b2b.com/orders?city_id=5&repertory_id=7&area_id=39 ...

  2. linq 在查询表达式中处理 null 值

    此示例显示如何在源集合中处理可能的 null 值. IEnumerable<T> 等对象集合可包含值为 null 的元素. 如果源集合为 null 或包含值为 null 的元素,并且查询不 ...

  3. 查询反模式 - GroupBy、HAVING的理解

    为了最简单地说明问题,我特地设计了一张这样的表. 一.GROUP BY单值规则 规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值. 典型的表现就是跟在SELEC ...

  4. 查询反模式 - GroupBy和HAVING的理解

    为了最简单地说明问题,我特地设计了一张这样的表. 一.GROUP BY单值规则 规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值. 典型的表现就是跟在SELEC ...

  5. LINQ查询表达式(5) - LINQ Null值处理&异常处理

    查询表达式中处理Null值 此示例演示如何处理源集合中可能的 null 值. 诸如 IEnumerable<T> 等对象集合可能包含值为 null 的元素. 如果源集合为 null 或包含 ...

  6. SQL反模式学习笔记1 开篇

    什么是“反模式” 反模式是一种试图解决问题的方法,但通常会同时引发别的问题. 反模式分类 (1)逻辑数据库设计反模式 在开始编码之前,需要决定数据库中存储什么信息以及最佳的数据组织方式和内在关联方式. ...

  7. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

  8. Oracle与Sqlserver:Order by NULL值介绍

    针对页面传参到in的子集中去进行查询操作的话,就会有in(xxx,null),这样就会导致查询的结果中其实直接过滤掉了null,根本就查不出来null的值.之前对于null的操作都是进行不同数据库的n ...

  9. SQL反模式学习笔记14 关于Null值的使用

    目标:辨别并使用Null值 反模式:将Null值作为普通的值,反之亦然 1.在表达式中使用Null: Null值与空字符串是不一样的,Null值参与任何的加.减.乘.除等其他运算,结果都是Null: ...

随机推荐

  1. 由于 UNION ALL Chinese_PRC_CI_AS”之间的排序规则冲突,值的排序规则未经解析

    由于不同的表之间的排序规则不一样,在归并集合的 时候会出现排序问题. 只要在查询的列后面 声明结果列的排序规则保持一致即可:  SELECT b0.[CardCode] collate SQL_Lat ...

  2. NSIS检测操作系统x64还是x86的问题。

    想共同维护一个NSIS脚本文件的,不想搞两个版本的脚本文件了.开始想到了!if语句,没试过,不知道行不行得通.后来google了一下.可以用两个头文件搞定.参照下面链接 Reference: http ...

  3. TextWatcher编辑框监听器

    TextWatcher tw = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int sta ...

  4. Linux 删除空行

    在Linux上处理一些数据文件时,有时候需要将其中的空行过滤掉,系统中提供的各种工具都可以完成这个功能.将常用的介绍如下吧:1. grep grep . data.txt grep -v '^$' d ...

  5. libjingle开发人员指南

    libjingle开发人员指南 libjingle SDK包含C + +源代码和文档,使您能够设计连接和网络交换数据的应用程序(通过点对点数据连接).该SDK包含代码和示例应用程序,一个Window平 ...

  6. bzoj2965

    http://www.lydsy.com/JudgeOnline/problem.php?id=2965 http://www.tsinsen.com/A1385 平面图网络流. 首先我们要将平面图转 ...

  7. MVC分部试图传参数

      @Html.Partial("_NavMenuPage", new ViewDataDictionary { { "proimshowId",imshowI ...

  8. 【剑指offer】面试题36:数组中的逆序对

    题目: 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 思路: 归并排序的合并过程.主要是考虑合并两个有序序列时,计算逆序 ...

  9. About Adultism and why things ar the way they are

    About - Adultism About Adultism and why things ar the way they are In this page we will try to clari ...

  10. Java常见内存溢出异常分析(OutOfMemoryError)

    原文转载自:http://my.oschina.net/sunchp/blog/369412 1.背景知识 1).JVM体系结构 2).JVM运行时数据区 JVM内存结构的相关可以参考: http:/ ...