in ,exists,any在数据库中数据失真的问题

简介

        早期文章已经介绍了in ,exists在数据库如果遇到空值会发生数据失真的情况,前段时间,又有人问到这一点,本篇文章再次对mysql8.0/oracle19c/postgresql-14进行测试,对于表中存在空值的集中匹配情况进行解析。

        插入测试数据   

--text_a作为主表,id作为关联字段
create table text_a(id int ,txt  varchar(10));
insert into text_a(id,txt)
values(1,'A');
insert into text_a(id,txt)
values(2,'A');
insert into text_a(id,txt)
values(3,'A');
insert into text_a(id,txt)
values(4,'A');
insert into text_a(id,txt)
values(5,'A');
insert into text_a(id,txt)
values(6,'A');
insert into text_a(id,txt)
values(7,'A');

--text_b作为匹配表,id作为关联字段
create table text_b(id int ,txt  varchar(10));
insert into text_b(id,txt)
values(1,'B');
insert into text_b(id,txt)
values(2,'B');
insert into text_b(id,txt)
values(3,'B');
insert into text_b(id,txt)
values(4,'B');
insert into text_b(id,txt)
values(5,'B');
insert into text_b(id,txt)
values(8,'B');

主表无空值,匹配表无空值。   

        测试        

select  *  from  text_a where id  = any (select  id from text_b);  --返回text_a全部结果



select  *  from  text_a where id  in (select  id from text_b);  --id = 6  7 符合预期


select  *  from  text_a where   exists (select  1 from text_b where text_a.id=text_b.id);  --id = 6  7 符合预期

 in ,exists,any在数据库中数据失真的问题_第1张图片

此测试在oracle/mysql/postgresql均做了测试,返回值均一致且符合预期

        在非的逻辑中区别就不一样了。

select  *  from  text_a where id  <> any (select  id from text_b);--返回text_a的全部结果  不及预期



select  *  from  text_a where id not in (select  id from text_b);  ----id = 6  7 符合预期


select  *  from  text_a where not exists (select  1 from text_b where text_a.id=text_b.id);
--id = 6  7 符合预期

 

 in ,exists,any在数据库中数据失真的问题_第2张图片

        在非的逻辑,<> any 的返回结果就不及预期,但是not in ,not exists 返回结果均符合 

主表无空值,匹配表有空值。 

        向匹配表中的关联字段中插入null 值

 insert into text_b(id,txt)
values(null,'B');

测试

        测试语句,本文只是列出在MySQL中的测试,实际结果和Oracle  postgresql三库的返回结果均为一致,不再一一列举

select  *  from  text_a where id  = any (select  id from text_b);
select  *  from  text_a where id  in (select  id from text_b);
select  *  from  text_a where    exists (select  1 from text_b where text_a.id=text_b.id);

in ,exists,any在数据库中数据失真的问题_第3张图片

        以上测试语句结果均为一致,数据情况正常,

在非的逻辑中返回的结果差异就比较大了

select  *  from  text_a where id  not in  (select  id from text_b);  --返回结果为空
select  *  from  text_a where id  <> any (select  id from text_b);  --返回结果为text_a表的全部数据
select  *  from  text_a where not exists (select  1 from text_b where text_a.id=text_b.id);--返回结果为id 6 ,7 两条数据

 

in ,exists,any在数据库中数据失真的问题_第4张图片

        在非的逻辑中,只有not exists 的返回结果符合 。

主表有空值,匹配表无空值。 

测试

        将以上text_a ,text_b 的主,副位置进行调换。

select  *  from  text_b where id  = any (select  id from text_a);
select  *  from  text_b where id  in (select  id from text_a);
select  *  from  text_b where    exists (select  1 from text_a where text_a.id=text_b.id);

in ,exists,any在数据库中数据失真的问题_第5张图片

        以上情况哎Oracle/mysql/postgresql返回结果均为正常且符合预期。

 在非逻辑的情况下

select  *  from  text_b where id  <> any (select  id from text_a);  --返回主表确实null值的全部结果,


select  *  from  text_b where id not in (select  id from text_a);  --返回id = 8 


select  *  from  text_b where not exists (select  1 from text_a where text_a.id=text_b.id);  --返回ID=8 ,null  符合预期

in ,exists,any在数据库中数据失真的问题_第6张图片

        此时也只有not exists  返回结果符合预期。

主表存在空值,匹配表存在空值

测试        

        此时text_a作为主表,text_b作为匹配表,向text_a中增加一个空值

insert into text_a(id,txt)
values(null,'A');
select  *  from  text_a where id  = any (select  id from text_b);


select  *  from  text_a where id  in (select  id from text_b);


select  *  from  text_a where exists (select  1 from text_b where text_a.id=text_b.id);

in ,exists,any在数据库中数据失真的问题_第7张图片

        在此语法中,测试了oracle/mysql/postgresql  返回结果均符合预期。

 

当在非的逻辑中

select  *  from  text_a where id  <> any (select  id from text_b);--返回除了null的全部结果


select  *  from  text_a where id not in (select  id from text_b);  --返回空值


select  *  from  text_a where not exists (select  1 from text_b where text_a.id=text_b.id);
--返回结果中,多了一个null  不及预期

in ,exists,any在数据库中数据失真的问题_第8张图片

        在本次测试了Oracle/mysql/postgresql ,三库返回情况均一致,三个语法均返回错误结果集。 

 总结

主/配 主null/配 主/配null 主null/配null
in true true true true
not in true false false false
any true true true true
<> any false false false false
exists true true true true
not exist true true true false

主null :代表主库关联字段存在null值

配null:代表匹配表关联字段存在null值

主:代表主库关联字段”不“存在null值

配:代表匹配表关联字段”不“存在null值

true:代表返回结果符合预期

false:代表返回结果不符合预期。造成数据失真。

你可能感兴趣的:(数据库)