故障013:易忘的NULL表达式

server/2024/12/16 2:46:40/

故障013:易忘的NULL表达式

    • 一、问题引入
    • 二、探索之路
      • 2.1 数据准备
      • 2.2 回顾NULL表达式
      • 2.3 重现问题
        • 2.3.1 分析原因
        • 2.3.2 如何化解预期?
    • 三、知识总结

一、问题引入

某单位开发人员理直气壮抛出一张截图,以红色醒目地标记问题,好似挑刺。咦!!!数据库不对头哟,等于或不等于查出结果一样,由此断定数据库可能有问题,过于决绝。这种陷阱极易掉进,因为等于和不等于不应该都相同的结果。如果没人深扒其原因,估计被人唬住。然而其本质原因是忽略表中的数据特征,一味地自发想象预期美好,不切实际分析问题。
在这里插入图片描述


二、探索之路

2.1 数据准备

sql">drop table if exists test01;
drop table if exists test02;
create table test01 (c1 int, c2 int , c3 int);
create table test02 (d1 int, d2 int , d3 int);insert into test01 values(1, 10, 11);
insert into test01 values(2, null, 12);
insert into test01 values(3, null, 13);
insert into test01 values(4, null, 14);insert into test02 values(1, null, 11);
insert into test02 values(2, 20, 12);
insert into test02 values(3, 30, 13);
insert into test02 values(4, 40, 14);
commit;

2.2 回顾NULL表达式

解释:NULL在数据库是一个特殊的存在,不是具体数据(暂时无法确定具体值,可能后期会赋予具体意义的值),属于一个抽象的占位符,表示某类型的未知数据,可以理解为数学方程式中的X(未知数,不确定性值)。


当然针对NULL的判断,数据库有专门的运算符比较,即IS NULL 或IS NOT NULL,而不是 = 、<>、 != 常规运算符,则遇见非IS NULL/IS NOT NULL的普通比较表达式,结果永远是false。请记住这个理论。

sql">-- 举例1:判断某表某列非空有哪些记录
-- 正确写法
select * from test01 where c2 is not null;
select * from test01 where not c2 is null;
select * from test01 where nvl(c2, '<NA!>') != '<NA!>' ;
select * from test01 where coalesce(c2, '<NA!>') != '<NA!>' ;
select * from test01 where isnull(c2, '<NA!>') != '<NA!>' ;
select * from test01 where ifnull(c2, '<NA!>') != '<NA!>' ;
select * from test01 where decode(c2, null, 0, 1) = 1;
select * from test01 where lnnvl(c2 is null);
select * from test01 where c2 > 0;  -- 知道该表C2字段数值分布,等效的写法-- 错误写法(返回空结果集)
select * from test01 where c2 != null;
select * from test01 where c2 <> null;-- 普通比较运算永远false(返回空结果集)
select * from test01 where c2 = null;
select * from test01 where c2 > null;
select * from test01 where c2 < null;

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


2.3 重现问题

模拟问题引入环节所说的场景,两表关联

sql">select count(*) -- 0
from test01 t1 
inner join test02 t2 on  t1.c1 = t2.d1
where t1.c2 = t2.d2; select count(*) -- 0
from test01 t1 
inner join test02 t2 on  t1.c1 = t2.d1
where t1.c2 != t2.d2; 

在这里插入图片描述

在这里插入图片描述

2.3.1 分析原因
sql">select t1.*, t2.* 
from test01 t1 
inner join test02 t2 on  t1.c1 = t2.d1;

在c1=d1等值关联条件成立情况下,进一步二级关联条件C2 = D2 或 C2 <> D2 ,从下图可知每次两表对二级关联条件匹配时存在一个NULL值,无论=、!= 比较运算,二级关联表达式永远false,导致最终结果集为空,正如count统计为零。

在这里插入图片描述

在这里插入图片描述

2.3.2 如何化解预期?

按他的预想是包含二级关联条件时存在NULL的情况,所以因在where过滤条件加入IS NULL判断。

sql">select t1.*, t2.* 
from test01 t1 
inner join test02 t2 on  t1.c1 = t2.D1
where t1.c2 = t2.d2 or t1.c2 is null or t2.d2 is null; select count(*) -- 4
from test01 t1 
inner join test02 t2 on  t1.c1 = t2.d1
where t1.c2 = t2.d2 or t1.c2 is null or t2.d2 is null;

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述


三、知识总结

1)编写SQL未按预期执行,应先思考SQL逻辑是否得当?再观察数据本身特征,不能盲目自认为。
2)SQL当中NULL往往易遗忘,正由它的特殊性存在,一旦未考虑全面,有可能结果集是非预期(可能遗漏有效数据或增多无效数据)。
3)建议数据表设定default默认值属性,减少NULL比较的可能性,减轻脑仁的负荷运转。


http://www.ppmy.cn/server/150509.html

相关文章

Redis02 SpringBoot整合Redis

使用方式 1.创建boot项目引入Web(Spring Web)NoSQl(Spring Data Redis(AccessDriver)) 2.修改配置文件 spring:redis:host: 127.0.0.1port: 6379password: 123456lettuce:pool:max-active: 8 #最大连接max-idle: 8 #最大空闲连接min-idle: 0 #最小空闲连接max-wait: 1000ms #…

vscode免密ssh登录ubantu 配置ubantu静态ip

1.vscode免密ssh登录ubantu 1、windows创建秘钥&#xff0c; 有秘钥就不用创建 ssh-keygen -t rsa2、将id_rsa.pub文件内的内容追加到ubantu的authorized_keys即可 2.配置ubantu静态ip 之前ubantu一直用的是动态ip&#xff0c;ubantu的ip变一次我就要从新配置一次ssh十分…

Python 程序与 Java 系统集成:通过 FastAPI 实现 HTTP 接口

要将你的 Python 程序封装为一个 API 服务&#xff0c;使得前后端 Java 系统能够通过 HTTP 调用&#xff0c;你可以使用 FastAPI 框架来实现。这是一个现代的、快速的 Web 框架&#xff0c;特别适合用于构建 APIs。FastAPI 支持自动生成 OpenAPI 文档&#xff0c;且性能非常高&…

linux下的posix信号量

目录 引言 信号量背景知识 PV操作 信号量接口 基于环形队列的PC模型 代码实现 demo模型 具体实现 引言 在多线程编程领域&#xff0c;同步机制是确保数据一致性和避免竞态条件的关键技术。Linux操作系统作为开源软件的杰出代表&#xff0c;提供了多种同步原语&#xf…

scala的Array

特性 类型安全&#xff1a;Scala 中的数组是类型安全的&#xff0c;这意味着一旦声明了数组的类型&#xff0c;就只能存储该类型的元素。 大小固定&#xff1a;数组的大小在创建时确定&#xff0c;之后不能改变。 零索引&#xff1a;Scala 数组与 Java 数组一样&#xff0c;都…

Centos 私有化部署示例——离线安装 screen

方式方法 在CentOS系统中&#xff0c;如果你无法直接使用yum或dnf命令进行在线安装&#xff0c;你可以采取以下步骤进行离线安装screen&#xff1a; 1. 在另一台有网络连接的机器上下载screen的rpm包。 2. 将下载的rpm包复制到你的CentOS机器上。 3. 使用rpm命令进行本地安…

OpenCV--特征检测

OpenCV--特征检测 代码和笔记 代码和笔记 import cv2 import numpy as np""" 特征检测和匹配 1. 定义&#xff1a;提取图像信息&#xff0c;决定每个图像的点是否属于一个图像特征。 特征检测的结果是把图像上的点分为不同的子集&#xff0c;这些子集往往属于孤…

SQL实现百分数转小数格式

MySQL 在MySQL中,可以使用CAST()函数将百分数转换为小数点格式。下面是一个示例: SELECT CAST(50% AS DECIMAL(4,2)) / 100;在上面的示例中,CAST(‘50%’ AS DECIMAL(4,2))将字符串’50%转换为DECIMAL类型,并指定小数点位数