关于ORACLE MYSQL NOT IN和NOT exists需要注意的 NULL值

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
云数据库 RDS PostgreSQL,高可用系列 2核4GB
简介: 首先说明NOT IN 和NOT EXISTS 并不完全等价 ORACLE MYSQL 都是如此 源表: SQL> select * from testa1; NAME                          ID ---------------...
首先说明NOT IN 和NOT EXISTS 并不完全等价 ORACLE MYSQL 都是如此
源表:
SQL> select * from testa1;
NAME                          ID
-------------------- -----------
gaopeng                        1
gaopeng                        2
gaopeng                        3
gaopeng                        4


SQL> select * from testb1;
NAME                          ID
-------------------- -----------
gaopeng                        1
gaopeng                        2
gaopeng              

因为NOT IN是对NULL 敏感的而NOT  exists却不是,所以ORACLE使用的执行计划如下:
select * from testa1 where  not exists (select * from testb1 where testa1.id=testb1.id );
NAME                          ID
-------------------- -----------
gaopeng                        4
gaopeng                        3

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4225223740
-----------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     4 |   152 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |        |     4 |   152 |     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| TESTA1 |     4 |   100 |     2   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| TESTB1 |     3 |    39 |     2   (0)| 00:00:01 |

普通的反连接


select * from testa1 where  testa1.id not in (select testb1.id from testb1  );

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2176127487
-----------------------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |        |     4 |   152 |     5  (20)| 00:00:01 |
|*  1 |  HASH JOIN ANTI NA |        |     4 |   152 |     5  (20)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| TESTA1 |     4 |   100 |     2   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| TESTB1 |     3 |    39 |     2   (0)| 00:00:01 |
-----------------------------------------------------------------------------
11g后改良的HASH JOIN ANTI NA 连接方式如果我们改变优化器到9I其执行计划为

select /*+ optimizer_features_enable('9.2.0') */ * from testa1 where  testa1.id not in (select testb1.id from testb1  );
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1097631637
-------------------------------------------------------------
| Id  | Operation          | Name   | Rows  | Bytes | Cost  |
-------------------------------------------------------------
|    0 | SELECT STATEMENT   |        |     4 |   100 |     4 |
|*   1 |  FILTER            |        |       |       |       |
|     2 |   TABLE ACCESS FULL| TESTA1 |     4 |   100 |     2 |
|*   3 |   TABLE ACCESS FULL| TESTB1 |    78 |  1014 |     2 |
-------------------------------------------------------------
可以看到老的执行计划是用不了的。

关于MYSQL 我也实验了一样和ORACLE一样 其执行计划如下:
mysql> explain select * from testa1 where  testa1.id not in (select testb1.id from testb1  );
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY     | testa1 | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
|  2 | SUBQUERY    | testb1 | ALL  | NULL          | NULL | NULL    | NULL |    3 | NULL        |
+----+-------------+--------+------+---------------+------+---------+------+------+-------------+
2 rows in set (0.00 sec)


mysql> explain select * from testa1 where  not exists (select * from testb1 where testa1.id=testb1.id );
+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+
| id | select_type        | table  | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+
|  1 | PRIMARY            | testa1 | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
|  2 | DEPENDENT SUBQUERY | testb1 | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using where |
+----+--------------------+--------+------+---------------+------+---------+------+------+-------------+

当然 in 和 exists 是等价的
相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
6月前
|
Oracle 关系型数据库 MySQL
Oracle linux 8 二进制安装 MySQL 8.4企业版
Oracle linux 8 二进制安装 MySQL 8.4企业版
173 1
|
8月前
|
SQL Oracle 关系型数据库
MySQL 和 Oracle 的区别?
本文对比了Oracle和MySQL数据库的多个方面。Oracle适用于大型数据库,支持高并发和大访问量,市场占有率为40%,安装占用空间较大,约3G;而MySQL适合中小型应用,是开源免费的,安装仅需152M。两者在主键生成、字符串处理、SQL语句、事务处理等方面存在差异。Oracle功能更为强大,尤其在企业级应用中表现突出,而MySQL则以简单易用见长。
932 7
MySQL 和 Oracle 的区别?
|
7月前
|
Oracle 关系型数据库 MySQL
使用崖山YMP 迁移 Oracle/MySQL 至YashanDB 23.2 验证测试
这篇文章是作者尚雷关于使用崖山YMP迁移Oracle/MySQL至YashanDB 23.2的验证测试分享。介绍了YMP的产品信息,包括架构、版本支持等,还详细阐述了外置库部署、YMP部署、访问YMP、数据源管理、任务管理(创建任务、迁移配置、离线迁移、校验初始化、一致性校验)及MySQL迁移的全过程。
|
9月前
|
监控 Oracle 关系型数据库
Mysql、Oracle审计日志的开启
通过上述步骤,可以在 MySQL 和 Oracle 数据库中启用和配置审计日志。这些日志对于监控数据库操作、提高安全性和满足合规性要求非常重要。确保正确配置审计参数和策略,定期查看和分析审计日志,有助于及时发现并处理潜在的安全问题。
493 11
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
2033 18
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
2187 3
|
12月前
|
Oracle 关系型数据库 MySQL
shell获取多个oracle库mysql库所有的表
请注意,此脚本假设你有足够的权限访问所有提到的数据库。在实际部署前,请确保对脚本中的数据库凭据、主机名和端口进行适当的修改和验证。此外,处理数据库操作时,务必谨慎操作,避免因错误的脚本执行造成数据损坏或服务中断。
148 0
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之从MySQL同步数据到Doris时,历史数据时间字段显示为null,而增量数据部分的时间类型字段正常显示的原因是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStreamAPI、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
SQL 关系型数据库 MySQL
python在mysql中插入或者更新null空值
这段代码是Python操作MySQL数据库的示例。它执行SQL查询从表`a_kuakao_school`中选取`id`,`university_id`和`grade`,当`university_id`大于0时按升序排列。然后遍历结果,根据`row[4]`的值决定`grade`是否为`NULL`。若不为空,`grade`被格式化为字符串;否则,设为`NULL`。接着构造UPDATE语句更新`university`表中对应`id`的`grade`值,并提交事务。重要的是,字符串`NULL`不应加引号,否则更新会失败。
296 2
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 IS NULL
【8月更文挑战第12天】
920 0
在 MySQL 中使用 IS NULL

推荐镜像

更多