在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. 转 linux 下装 usb driver

    http://www.george-smart.co.uk/wiki/Xilinx_JTAG_Linux

  2. 常见报表的JS代码

    1.合并单元格 这个表格在报表里面算是比较典型的 1.里面的表格的列标题现在是写死的,其实这些可以通过配置进行 2.至于如果表头要进行合并(这种需求比较少,也比较容易实现) 3.至于统计:最好在后台按 ...

  3. 使用JdbcTemplate访问数据库

    参考源端:https://blog.csdn.net/liaodehong/article/details/76974827 今天用Spring Boot访问一下数据库,并且把数据返回到页面中,进行增 ...

  4. JavaScript Promise的学习笔记

    首先声明:本人今天刚接触Promise,通过一个例子,希望能更好的来理解,如果有不对的地方,还望指正 Promise是专门为解决 js中回调而引起的各种问题,而产生的. 在异步编程中,我们经常使用回调 ...

  5. 36. Valid Sudoku + 37. Sudoku Solver

    ▶ 有关数独的两个问题. ▶ 36. 检测当前盘面是否有矛盾(同一行.同一列或 3 × 3 的小框内数字重复),而不关心该盘面是否有解. ● 初版代码,24 ms,没有将格子检测函数独立出去,行检测. ...

  6. pandas的数据结构

    要使用pandas,需要熟悉它的两个主要的数据结构,Series和DataFrame. Series series是一种类似于以为数组的对象,它由一组数据(各种numpy的数据类型)以及一组与之相关的 ...

  7. JS调用webservice的两种方式

    协议肯定是使用http协议,因为soap协议本身也是基于http协议.期中第二种方式:只有webservice3.5以后版本才可以成功 第一种方式:构造soap格式的body,注意加粗的黄色标识,比如 ...

  8. Redis 集群二

    [Redis 集群二] 集群的客户端 Redis 集群现阶段的一个问题是客户端实现很少. 以下是一些我知道的实现: redis-rb-cluster 是我(@antirez)编写的 Ruby 实现, ...

  9. pymysql.err.IntegrityError: (1062, "Duplicate entry 'roxml-ROXML' for key 'PRIMARY'")

    在<Python数据挖掘-概念.方法与实践>一书的第3章实体匹配中,如果一路按照作者的代码及SQL语句进行配置运行的话,会出现如题目所示的错误.根据python脚本的执行错误提示显示,错误 ...

  10. sqlserver流程控制(待续)

    if else: if(1=1) begin--必须1个=号print '111'--begin end 之间必须要有内容end else beginprint '222'end while: DEC ...