TSQL--NULL值和三值逻辑
在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值和三值逻辑的更多相关文章
- 数据库 SQL :有关 NULL 值引发 TRUE、FALSE、UNKNOW 三值逻辑
在 Java.C# 中,相信如果是 boolean 类型值,只有两种选择 true.false.然而,在 SQL 查询中,NULL 值的引入,使得新增了 UNKNOW ,因此,就产生了 TRUE.FA ...
- TSQL 聚合函数忽略NULL值
max,min,sum,avg聚合函数会忽略null值,但不代表聚合函数不返回null值,如果表为空表,或聚合列都是null,则返回null.count 聚合函数忽略null值,如果聚合列都是null ...
- SqlServer中的Null值空值问题
sql使用的是三值谓词逻辑,所以逻辑表达式返回的结果可以为True.False或者未知,在三值逻辑中返回True与不返回False并不完全一样, SQL对查询过滤条件的处理:接受TURE 拒绝FAL ...
- SQL中的NULL值
除is [not] null之外,空值不满足任何查找条件.–如果null参与算术运算,则该算术表达式的值为null.–如果null参与比较运算,则结果可视为false.在SQL-92中可看成unkno ...
- 不再迷惑,无值和NULL值的转换
在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,心有戚戚焉,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的决心(开 ...
- 不再迷惑,无值和NULL值
在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,战战兢兢,如履薄冰,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的 ...
- 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结
为什么说JAVA中要慎重使用继承 这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...
- oracle 关于null值排序
在oracle中根据字段来desc排序的话null值可能会在数据的最前面.然而有时候我们查看数据的时候并不希望能够在前面看到这些null值的排序数据. 因此我查了一下: 1.排序的时候运用nvl(). ...
- SQL中NULL值
SQL的表达式,除了IS NULL和NOT NULL以外,只要出现NULL值结果都为FALSE 简单的例子: SELECT * FROM table WHERE name!='abc' 只要name值 ...
- 关于null值的排序
关于空值null的排序问题 Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...
随机推荐
- 0001_mysql 5.7.25安装初始化
一. 下载mysql https://dev.mysql.com/downloads/mysql/ 二. 选择社区版本 三. 选择版本下载: 四. 跳过注册直接下载: 五. 解压后 ...
- Autofac框架详解
一.组件 创建出来的对象需要从组件中来获取,组件的创建有如下4种(延续第一篇的Demo,仅仅变动所贴出的代码)方式: 1.类型创建RegisterType AutoFac能够通过反射检查一个类型,选择 ...
- CentOS 6.7 编译PHP7 make时出现错误:undefined reference to `libiconv_close’
编辑Makefile文件,找到变量EXTRA_LIBS,并在末尾添上-liconv EXTRA_LIBS = -lcrypt -lz -lexslt -lcrypt -lrt -lmcrypt -ll ...
- windows下手动安装pyinstaller(python2.7)
1.首先,安装python2.7.13,官网下载msi版(windows直接安装): https://www.python.org/downloads/ 2.然后,到python包官网依次下载,fut ...
- leetcode561
public class Solution { public int ArrayPairSum(int[] nums) { var list = nums.OrderBy(x => x).ToL ...
- windows下使用nginx配置tomcat集群
转自:https://blog.csdn.net/csdn15698845876/article/details/80658599
- delphi 触摸 手势
delphi手势,左右滑动, 控件的OnGesture事件写代码. 放一个TGestureManager控件,设置控件的touch属性为TGestureManager控件. 然后勾选控件的Touch& ...
- 横向文本框 cursor:pointer 出现手型
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- java JDBC数据库连接操作
import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public clas ...
- nodejs API(二)
官网所在位置:https://nodejs.org/dist/latest-v6.x/docs/api/querystring.html querystring.escape(str) 转义 qu ...