0
点赞
收藏
分享

微信扫一扫

DBA一定要告诉开发人员数据失真的情况之一

简介

今天看到白鳝老师的一篇文章说《你的PG数据安全准确吗》,主要讲postgresql数据库在数据文件丢失的情况下,对其增、删、改、查不会报错,但是数据会出现失真,所以今天想写一篇在开发人员使用数据库中使用in ,exists,any语法造成数据失真的情况。早前关于此类问题在我CSDN博客有过发表。

本文以postgresql14.7\mysql8.0.26\oracle19C 三个数据库版本进行试验

插入测试数据

--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');

1.主表、匹配表均无空值的情况。

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

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 符合预期
此时主表和匹配表在没有NULL值得情况,返回的结果集均符合预期,没有出现数据失真

DBA一定要告诉开发人员数据失真的情况之一_字段

此测试在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 符合预期

DBA一定要告诉开发人员数据失真的情况之一_数据_02

此测试在oracle/mysql/postgresql均做了测试,返回值均一致

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

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

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

测试其返回结果

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);

以上结果中返回值均正常,且三个数据库返回值均一致

DBA一定要告诉开发人员数据失真的情况之一_字段_03


有意思的来了,同样的数据集,在非的逻辑中区别就不一样了。

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 两条数据 符合预期

DBA一定要告诉开发人员数据失真的情况之一_数据_04


DBA一定要告诉开发人员数据失真的情况之一_数据_05

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

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

select  *  from  text_b where id  = any (select  id from text_a); --返回id=1、2、3、4、5 符合预期

select  *  from  text_b where id  in (select  id from text_a);--返回id=1、2、3、4、5 符合预期

select  *  from  text_b where    exists (select  1 from text_a where text_a.id=text_b.id);--返回id=1、2、3、4、5 符合预期

其实以上逻辑都是一个内连接的关系,当主副表互换位置,数据结果就返回正常了。

DBA一定要告诉开发人员数据失真的情况之一_字段_06


以上情况在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  符合预期

DBA一定要告诉开发人员数据失真的情况之一_字段_07


DBA一定要告诉开发人员数据失真的情况之一_返回结果_08


此时也只有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); --返回ID=1、2、3、4、5均符合预期
select  *  from  text_a where id  in (select  id from text_b);--返回ID=1、2、3、4、5均符合预期
select  *  from  text_a where exists (select  1 from text_b where text_a.id=text_b.id);--返回ID=1、2、3、4、5均符合预期

此时结果返回均正常
有意思的来了,在非逻辑的情况下就不一样了

select  *  from  text_a where id  <> any (select  id from text_b);--返回id=1、2、3、4、5、6、7的全部结果 
 
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); --返回id=6、7、null  不及预期

以上结果返回值均不一样,且均不符合预期,均发生数据失真的情况。

DBA一定要告诉开发人员数据失真的情况之一_字段_09


DBA一定要告诉开发人员数据失真的情况之一_返回结果_10


DBA一定要告诉开发人员数据失真的情况之一_字段_11

总结

DBA一定要告诉开发人员数据失真的情况之一_数据_12

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

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

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

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

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

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

白鳝老师的今日一篇文章说《你的PG数据安全准确吗》感兴趣的话可以看看我后面的转载。

举报

相关推荐

0 条评论