网站首页 > 技术文章 正文
在查询数据库时,如果你想知道一个列是否为 NULL,SQL 查询语句该怎么写呢?
是不是这样:
SELECT * FROM SOME_TABLEWHERE SOME_COLUMN IS NULL
或者这样写:
复制代码
WHERE SOME_COLUMN = 1
正确的写法应该是第二种(WHERE SOME_COLUMN IS NULL)。
为什么要这样写?
在进行数据库数据比较操作时,我们不会使用“IS”关键词,不是吗?
例如,如果我们想要知道一个列的值是否等于 1,WHERE 语句是这样的:
复制代码
WHERE SOME_COLUMN = 1
那为什么 NULL 值要用 IS 关键字呢?为什么要以这种方式来处理 NULL?
因为,在 SQL 中,NULL 表示“未知”。也就是说,NULL 值表示的是“未知”的值。
NULL 等于未知
在大多数数据库中,NULl 和空字符串是有区别的。
但并不是所有数据库都这样,例如,Oracle 就不支持空字符串,它会把空字符串自动转成 NULL 值。
在其他大多数数据库里,NULL 值和字符串的处理方式是不一样的:
- 空字符串表示“没有值”,这个值是已知的。
- NULL 表示“未知值”,这个值是未知的。
这就好比我问了一个问题:“美国总统罗斯福的中间名是什么”?
- 可能有人会回答说:“我不知道罗斯福总统的中间名是什么”。对于这种情况,可以在数据库中使用 MIDDLE_NAME 列来表示罗斯福的中间名,而这一列的值为 NULL。
- 也可能有人会回答说:“罗斯福总统没有中间名。他的父母没有给他取中间名,所以我知道罗斯福总统确实没有中间名”。对于这种情况,MIDDLE_NAME 列应该是一个空字符串。
Oracle 比较特殊,两个值都使用 NULL 来表示,而其他大多数数据库会区分对待。
但只要记住 NULL 表示的是一个未知的值,那么在写 SQL 查询语句时就会得心应手。
例如,如果你有一个这样的查询语句:
复制代码
SELECT * FROM SOME_TABLEWHERE 1 = 1
这个查询会返回所有的行(假设 SOME_TABLE 不是空表),因为表达式“1=1”一定为 true。
如果我这样写:
复制代码
SELECT * FROM SOME_TABLEWHERE 1 = 0
表达式“1=0”是 false,这个查询语句不会返回任何数据。
但如果我写成这样:
复制代码
SELECT * FROM SOME_TABLEWHERE 1 = NULL
这个时候,数据库不知道这两个值(1 和 NULL)是否相等,所以它也不会返回任何数据。
三元逻辑
SQL 查询语句中的 WHERE 一般会有三种结果:
- 它可以是 true(这个时候会返回数据);
- 它可以是 false(这个时候不会返回数据);
- 它也可以是 NULL 或未知(这个时候也不会返回数据)。
你可能会想:“既然这样,那我为什么要去关心是 false 还是 NULL?它们不是都不会返回数据吗?”
接下来,我来告诉你在哪些情况下会有问题:我们来看看 NOT()。
假设有这样的一个查询语句:
复制代码
SELECT * FROM SOME_TABLEWHERE NOT(1 = 1)
数据库首先会计算 1=1,这个显然是 true。
接着,数据库会应用 NOT() 条件,所以 WHERE 返回 false。
所以,上面的查询不会返回任何数据。
但如果把语句改成这样:
复制代码
SELECT * FROM SOME_TABLEWHERE NOT(1 = 0)
数据库首先会计算 1=0,这个肯定是 false。
接着,数据库应用 NOT() 条件,这样就得到相反的结果,变成了 true。
所以,这个语句会返回数据。
但如果把语句再改成下面这样呢?
复制代码
SELECT * FROM SOME_TABLEWHERE NOT(1 = NULL)
数据库首先计算 1=NULL,它不知道 1 是否等于 NULL,因为它不知道 NULL 的值是什么。
所以,这个计算不会返回 true,也不会返回 false,它会返回一个 NULL。
接下来,NOT() 会继续解析上一个计算返回的结果。
当 NOT() 遇到 NULL,它会生成另一个 NULL。未知的相反面是另一个未知。
所以,对于这两个查询:
复制代码
SELECT * FROM SOME_TABLEWHERE NOT(1 = NULL)
和
复制代码
SELECT * FROM SOME_TABLEWHERE 1 = NULL
都不会返回数据,尽管它们是完全相反的。
NULL 和 NOT IN
如果我有这样的一个查询语句:
复制代码
SELECT * FROM SOME_TABLEWHERE 1 IN (1, 2, 3, 4, NULL)
很显然,WHERE 返回 true,这个语句将返回数据,因为 1 在括号列表里是存在的。
但如果这么写:
复制代码
SELECT * FROM SOME_TABLEWHERE 1 NOT IN (1, 2, 3, 4, NULL)
很显然,WHERE 返回 false,这个查询不会返回数据,因为 1 在括号列表里存在,但我们说的是“NOT IN”。
但如果我们把语句改成这样呢?
复制代码
SELECT * FROM SOME_TABLEWHERE 5 NOT IN (1, 2, 3, 4, NULL)
这里的 WHRE 不会返回数据,因为它的结果不是 true。数字 5 在括号列表里可能不存在,也可能存在,因为当中有一个 NULL 值(数据库不知道 NULL 的值是什么)。
这个 WHERE 会返回 NULL,所以整个查询不会返回任何数据。
希望你们现在都清楚该怎么在 SQL 语句中处理 NULL 值了。
英文原文
Null Values in SQL Queries
中文译文:https://www.infoq.cn/article/CKm0rLd6VZaSxj6iR1ib
猜你喜欢
- 2024-11-16 Oracle 21c 新特性:不可变表 Immutable tables 提高安全
- 2024-11-16 读SQL进阶教程笔记14_SQL编程要点
- 2024-11-16 分享SQL语句书写规范(分享sql语句书写规范是什么)
- 2024-11-16 oracle——空字符串('')不能用和!=
你 发表评论:
欢迎- 07-10Oracle 与 Google Cloud 携手大幅扩展多云服务
- 07-10分享收藏的 oracle 11.2.0.4各平台的下载地址
- 07-10Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- 07-10Oracle Database@Azure 推进到南美等新区域并增加了新服务
- 07-10Oracle宣布推出 Oracle Database@AWS 的有限预览版
- 07-10Oracle与Nextcloud合作,推出主权云上的安全协作平台
- 07-10NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 07-10对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 605℃几个Oracle空值处理函数 oracle处理null值的函数
- 597℃Oracle分析函数之Lag和Lead()使用
- 585℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 581℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 577℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 570℃【数据统计分析】详解Oracle分组函数之CUBE
- 557℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 550℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
-
- Oracle 与 Google Cloud 携手大幅扩展多云服务
- 分享收藏的 oracle 11.2.0.4各平台的下载地址
- Oracle 和 Microsoft 推出 Oracle Exadata 数据库服务
- Oracle Database@Azure 推进到南美等新区域并增加了新服务
- Oracle宣布推出 Oracle Database@AWS 的有限预览版
- Oracle与Nextcloud合作,推出主权云上的安全协作平台
- NodeRED魔改版连接MsSql、PostgreSQL、MySQL、OracleDB存储无忧
- 对于企业数据云备份,“多备份”承诺的是成本更低,管理更高效#36氪开放日深圳站#
- 解读丨《归档文件整理规则》— 电子文件元数据存储
- Data Guard跳归档恢复的实践(dataguard failover)
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (57)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)