SQL进价2:三值逻辑和null

1、SQL中的bool类型的值有三种

普通编程语言里的布尔型只有 truefalse 两个值,这种逻辑体系被称为二值逻辑。而 SQL 语言里,除此之外还有第三个值 unknown,因此这种逻辑体系被称为三值逻辑(three-valued logic)。

2、null不是值,与数学运算符结果的结果永远是unknown

常听到的“列的值为 NULL” 、“NULL 值”这样的说法本身就是错误的。因为 NULL 不是值NULL 不是值NULL 不是值!(如果有人认为 NULL 是值,那么它是什么类型的值?关系数据库中存在的值必然属于某种类型,比如字符型或数值型等。所以,假如 NULL 是值,那么它就必须属于某种类型。)

另外,注意:要想和null比较只能用 is null 或者 is not null,这样才会返回true或者false。另外永远记住一点,null和<,<,=,<>这些放在一起结果永远是unknown,如 2=null,结果肯定是unknown,而unknown可在三值逻辑中不是true或者false,在写where子句的筛选条件时尤其要注意。举例来讲:

接下来我们总结一下 SQL 遵循的三值逻辑的真值规律(理解下面这些非常重要)。

先看下图:(t:true,f:false,u:unknown。not unknown 的结果是 unknown)

我们经常会遇到判断筛选条件的结果(为true/false/unknown的一种,且SQL只会取返回结果是true的记录),它们通常是and 或or连接这些单个条件的,如:where age>18 and sex=0或where age<18 and sex =unknown。所以我们要牢牢记住上面这个图,才能对各种情况下返回的数据心里有底。

记忆方式1:

and运算,只要有一边是unknown,另一边是false,那结果就是false,其它情况下,只要任意一边有unknown,结果就是unknown。

or运算,只要一边是unknown,那么结果永远就是unknown

记忆方式2:

在判断and或or的最终结果时,请注意true/false/unknown之间有下面这样的优先级顺序。

  • AND 的情况:falseunknowntrue

  • OR 的情况:trueunknownfalse

优先级高的真值会决定计算结果。例如 true AND unknown,因为 unknown 的优先级更高,所以结果是 unknown。而 true OR unknown 的话,因为 true 优先级更高,所以结果是 true。记住这个顺序后就能更方便地进行三值逻辑运算了。特别需要记住的是,当 AND 运算中包含 unknown 时,结果肯定不会是 true(反之,如果 AND 运算结果为 true,则参与运算的双方必须都为 true)。这一点对理解后文非常关键。

3、NOT IN 和 NOT EXISTS 不是等价的

如果 NOT IN 子查询中用到的表里被选择的列中存在 NULL,则 SQL 语句整体的查询结果永远是空。EXISTS 谓词永远不会返回 unknownEXISTS 只会返回 true 或者 false。因此就有了 INEXISTS 可以互相替换使用,而 NOT INNOT EXISTS 却不可以互相替换的混乱现象。

4、ALL运算符与null

以下是ALL运算符语法:

scalar_expression comparison_operator ALL ( subquery )

在上面语法中,

  • scalar_expression是任何有效的表达式。

  • comparison_operator是任何有效的比较运算符,包括等于(=),不等于(<>),大于(>),大于或等于(>=),小于(<),小于或等于(<=)。
  • 括号内的子查询(subquery)是一个SELECT语句,它返回单个列的结果。 此外,返回列的数据类型必须与标量表达式的数据类型相同。

如果所有比较对(scalar_expression,v)的计算结果为TRUE,则ALL运算符返回TRUE; v是单列结果中的值。

如果其中一对(scalar_expression,v)返回FALSE,则ALL运算符返回FALSE

如果all里面的子查询返回的单列中有null的存在,那么这个all表达式就永远不会筛选出任何数据,结果肯定为空。

因为ALL 谓词其实是多个以 AND 连接的逻辑表达式的省略写法

如果all里面的子查询返回的单列中有null的存在,比如子查询结果如下面这个情况,那么具体的分析步骤如下所示。

--1. 执行子查询获取年龄列表
SELECT *
  FROM Class_A
 WHERE age < ALL ( 22, 23, NULL );
--2. 将ALL 谓词等价改写为AND
SELECT *
  FROM Class_A
 WHERE (age < 22) AND (age < 23) AND (age < NULL);
--3. 对NULL 使用“<”后,结果变为 unknown
SELECT *
  FROM Class_A
 WHERE (age < 22) AND (age < 23) AND unknown;
--4. 如果AND 运算里包含unknown,则结果不为true
SELECT *
  FROM Class_A
 WHERE false 或 unknown;
--5.查询结果为空

原文地址:https://www.cnblogs.com/gds-1202b/p/10796854.html

时间: 2024-10-10 02:59:25

SQL进价2:三值逻辑和null的相关文章

SQL Server 排序的时候使 null 值排在最后

最近遇到一个 SQL Server 排序的问题,以前也没了解过,然后这次碰到了. 才发现 SQL Server 排序的问题,在指定的排序列中 null 值会默认排在最前面,因为在 SQL Server 中 null 值默认为最小值. 后来问了一下万能的百度,找到了下面一种比较简单的处理方法. 首先建了一个表插入了一些测试数据. create table UserInfo ( UserInfoID int not null identity(1,1) primary key, User_No in

Spark SQL中Dataframe join操作含null值的列

当在Spark SQL中对两个Dataframe使用join时,当作为连接的字段的值含有null值.由于null表示的含义是未知,既不知道有没有,在SQL中null值与任何其他值的比较(即使是null)永远不会为真.故在进行连接操作时null == null不为True,所以结果中不会出现该条记录,即左侧表格的这条记录对应右侧的值均为null.示例如下: table_a: date serverId lvSection 2018-03-04 1 10 2018-03-05 null 9 2018

SQL总结(三)其他查询

SQL总结(三)其他查询 其他常用的SQL,在这里集合. 1.SELECT INTO 从一个表中选取数据,然后把数据插入另一个表中.常用于创建表的备份或者用于对记录进行存档. 语法: SELECT column_name(s) INTO new_table_name [IN externaldatabase] FROM old_tablename IN 子句可用于向另一个数据库中拷贝表. 1)备份表信息 SELECT ID,Name INTO Students_Backup FROM Stude

防止sql注入的三种方法

常用的避免SQL注入的三种方法 一,存储过程 在学习数据库视频的时候接触过,它是存储在数据库中的一些事先编译好的指令.在用的时候不用重新编写,直接调用就好了.所以,使用它可以大大提高程序的执行效率. 那么,如果创建一个存储程序并使用它呢?这是我们今天要解决的问题 1.创建过程 可编程性--下拉菜单--存储过程--右键--查询菜单--指定模板参数的值--新建查询--输入语句--查询菜单中的分析检查语法是否正确--执行 2.具体创建语法 在创建存储程序时,为了应对各种变换的数据,通常会涉及到带参数的

SQL入门经典(三) 之连接查询

上一篇介绍到查询.这一篇主要讲连接查询,将介绍INNER JOIN,OUTER JOIN(LEFT和RIGHT),FULL JOIN,CROSS JOIN. 连接顾名斯义就是把多个数据表数据合并到一个结果集. 用内部连接检索匹配的数据(inner join) 连接结构语法如下:SELECT <column list> FROM <first table>  <join_type> <last table> [ON <join condition>

获取动态SQL查询语句返回值(sp_executesql)

在写存储过程时经常会遇到需要拼接SQL语句的情况,一般情况下仅仅是为了执行拼接后的语句使用exec(@sql)即可. 而今天的一个存储过程却需要获取动态SQL的查询结果. 需求描述:在某表中根据Id值查询Cost值(表名不确定但表结构确定,如下面的Product表) 如果不考虑获取返回值,我们这样写即可: declare @tableName varchar(50) declare @id varchar(10) declare @cost numeric(18,2) declare @sql

SQL Server之 (三) 分组 类型转换函数 插入多条数据 字符串函数

SQL Server之 (三)  分组 类型转换函数  插入多条数据  字符串函数 自己学习笔记,转载请注明出处,谢谢!---酸菜 1.SQL 数据分组----Group by /Having  ①有一学生信息表:StuID/StuName/StuAge/StuGender/StuClassID; 求每个班级的ID和对应人数:select StuClassID 班级ID,count(*) 班级人数  from StuInfo group by StuClassID ; 求所有同学中男女同学对应人

不再迷惑,无值和NULL值

在关系型数据库的世界中,无值和NULL值的区别是什么?一直被这个问题困扰着,甚至在写TSQL脚本时,战战兢兢,如履薄冰,害怕因为自己的一知半解,挖了坑,贻害后来人,于是,本着上下求索,不达通幽不罢休的决心(开个玩笑),遂有此文. 学习过关系型数据库的伙伴都知道,NULL是指不确定的值,在数据库中绝对是噩梦的存在:而空值,一般对字符串类型而言,指没有任何值的字符串类型,为字符类型的变量设置为空值:set @vs='',空值跟无值不同.有人可能会问,无值是什么?无值,是指数据表中没有任何数据.无值和

从DB灌值到DataTable时,字段值为NULL时报错相关信息;

报错信息: 1.  2.  3.  4.  5.  6.  解决方法: 1. Data Layer SQL 语句取数据时,把其列值有为null的字段用0.00替换,(ISNULL的用法): 2. 1 #region 查询工资信息 2 /// <summary> 3 /// 查询工资信息 4 /// </summary> 5 /// <param name="model"></param> 6 /// <param name=&quo