在SQL SERVER 中逻辑表达式存在三种值:TRUE+FALSE+UNKNOWN。UNKNOW可以理解为不确定,既不是TRUE又不是FALSE的表达式,主要由与NULL相关的逻辑判断引起,值为NULL就意味着该未赋值或该值未确定。

与NULL值做算术运算时,其结果是NULL,如果1+NULL结果为NULL

SQL Server不同场景下对UNKNOWN处理不同,对NULL的处理也不同。

1. 在WHERE+ON+HAVING三种筛选器中,所有运算结果非TURE(FALSE 与UNKNOW)的记录都不会返回;

2. 在CHECK约束中,所有运算结果为非FALSE(TRUE与UNKNOW)的都属于满足CHECK约束的;

3. 在UNIQUE约束中,如果列定义未限制为NOT NULL,那么允许该列存在一条NULL值,如果另外插入或更新一条记录为NULL时,会违法UNIQUE约束,NULL与NULL是相等的;

4. 在GROUP BY中,NULL值被认为相同而分为一组,NULL与NULL是相等的;

5. 在ORDER BY中,NULL值被认为相同而排列在一起,所有NULL值比已知值小,NULL与NULL是相等的;

除上述3/4/5条中提到的情况外,NULL与NULL是不相等的。

默认情况下,即SET ANSI_NULLS ON时,对于条件(WHERE C1 = NULL)这种查询,C1列值为NULL的行不会被返回;

而当SET ANSI_NULLS ON时,对于条件(WHERE C1 = NULL)这种查询,C1列值为NULL的行会被返回,此时C1=NULL应该被理解为做C1 IS NULL 运算,而不应该理解为NULL与NULL相等;

理解混乱的同学可以做以下测试:

--==========================================
--生成测试数据
DECLARE @TB TABLE
(
C1 INT
) INSERT INTO @TB
SELECT 1
UNION
SELECT NULL --===========================================
--修改默认选项值,设置ANSI_NULLS
--注意该设置是回话级别,而不是批处理级别或语句级别
SET ANSI_NULLS OFF; --============================================
--当ANSI_NULLS OFF时,C1=NULL 等同于C1 IS NULL
--因此查询返回一条NULL的记录
SELECT * FROM @TB
WHERE C1=NULL --============================================
--当ANSI_NULLS OFF,NULL与NULL仍不认为相等
--因此查询中不会返回NULL的记录
SELECT * FROM @TB AS TB1
INNER JOIN @TB TB2
ON TB1.C1=TB2.C1

运行结果为:

为规范操作和避免混乱,强烈建议使用IS NULL 和IS NOT NULL判断值是否为NULL,避免修改默认选项ANSI_NULLS为OFF。

除上面提到的特殊情况外,由于NULL与NULL是不相等的,因此

1. 在做IN和EXISTS运算如WHERE C1 IN(SELECT ID FROM TB1) 或者 WHERE EXISTS (SELECT ID FROM TB1 WHERE ID =C1)时,所有C1列为NULL的行都不会被返回,无论表TB1的ID列是否存在NULL值;

2. 对NOT IN运算如T1.C1 NOT IN (SELECT T2.C1 FROM T2) 时,如果表T2的C1列存在NULL值, 那么查询将不会返回任何记录,无论表T1的C1列是否有NULL值存在。

3. 对NOT EXISTS运算如NOT EXISTS(SELECT C1 FROM T2 WHERE T2.C1=T1.C1),会返回T1表有但T2表没有且T1.C2 IS NOT NULL的记录

测试DEMO

--=================
--生成测试数据
DECLARE @TB TABLE
(
C1 INT
) DECLARE @TB2 TABLE
(
C1 INT
) INSERT INTO @TB
SELECT 1
UNION
SELECT 2 INSERT INTO @TB2
SELECT 1
UNION
SELECT NULL --=================================
--NOT EXISTS返回记录为2的行
SELECT * FROM @TB AS TB1
WHERE NOT EXISTS(
SELECT C1 FROM @TB2 AS TB2
WHERE TB2.C1=TB1.C1)
--================================
--NOT IN 不返回任何行
SELECT * FROM @TB
WHERE C1 NOT IN
(
SELECT C1 FROM @TB2
)

因此,IN和EXIST可以相互改写,但是NOT IN不能随便改写为NOT EXISTS.

PS: 对于运算结果为UNKNOW的逻辑表达式,再做NOT运算,结果仍未UNKNOW

--==========================================================

妹子振贴

TSQL--NULL值和三值逻辑的更多相关文章

  1. 数据库 SQL :有关 NULL 值引发 TRUE、FALSE、UNKNOW 三值逻辑

    在 Java.C# 中,相信如果是 boolean 类型值,只有两种选择 true.false.然而,在 SQL 查询中,NULL 值的引入,使得新增了 UNKNOW ,因此,就产生了 TRUE.FA ...

  2. TSQL 聚合函数忽略NULL值

    max,min,sum,avg聚合函数会忽略null值,但不代表聚合函数不返回null值,如果表为空表,或聚合列都是null,则返回null.count 聚合函数忽略null值,如果聚合列都是null ...

  3. SqlServer中的Null值空值问题

    sql使用的是三值谓词逻辑,所以逻辑表达式返回的结果可以为True.False或者未知,在三值逻辑中返回True与不返回False并不完全一样, SQL对查询过滤条件的处理:接受TURE  拒绝FAL ...

  4. SQL中的NULL值

    除is [not] null之外,空值不满足任何查找条件.–如果null参与算术运算,则该算术表达式的值为null.–如果null参与比较运算,则结果可视为false.在SQL-92中可看成unkno ...

  5. 不再迷惑,无值和NULL值的转换

    在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,心有戚戚焉,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的决心(开 ...

  6. 不再迷惑,无值和NULL值

    在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,战战兢兢,如履薄冰,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的 ...

  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 关于null值排序

    在oracle中根据字段来desc排序的话null值可能会在数据的最前面.然而有时候我们查看数据的时候并不希望能够在前面看到这些null值的排序数据. 因此我查了一下: 1.排序的时候运用nvl(). ...

  9. SQL中NULL值

    SQL的表达式,除了IS NULL和NOT NULL以外,只要出现NULL值结果都为FALSE 简单的例子: SELECT * FROM table WHERE name!='abc' 只要name值 ...

  10. 关于null值的排序

    关于空值null的排序问题   Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...

随机推荐

  1. 0001_mysql 5.7.25安装初始化

    一.   下载mysql https://dev.mysql.com/downloads/mysql/ 二.   选择社区版本 三.   选择版本下载: 四.   跳过注册直接下载: 五.   解压后 ...

  2. Autofac框架详解

    一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...

  3. CentOS 6.7 编译PHP7 make时出现错误:undefined reference to `libiconv_close’

    编辑Makefile文件,找到变量EXTRA_LIBS,并在末尾添上-liconv EXTRA_LIBS = -lcrypt -lz -lexslt -lcrypt -lrt -lmcrypt -ll ...

  4. windows下手动安装pyinstaller(python2.7)

    1.首先,安装python2.7.13,官网下载msi版(windows直接安装): https://www.python.org/downloads/ 2.然后,到python包官网依次下载,fut ...

  5. leetcode561

    public class Solution { public int ArrayPairSum(int[] nums) { var list = nums.OrderBy(x => x).ToL ...

  6. windows下使用nginx配置tomcat集群

    转自:https://blog.csdn.net/csdn15698845876/article/details/80658599

  7. delphi 触摸 手势

    delphi手势,左右滑动, 控件的OnGesture事件写代码. 放一个TGestureManager控件,设置控件的touch属性为TGestureManager控件. 然后勾选控件的Touch& ...

  8. 横向文本框 cursor:pointer 出现手型

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. java JDBC数据库连接操作

    import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public clas ...

  10. nodejs API(二)

    官网所在位置:https://nodejs.org/dist/latest-v6.x/docs/api/querystring.html querystring.escape(str) 转义   qu ...