SQL聚合函数SUM值为NULL引发的爆炸

简介: 在写这篇文章之前,最想提醒大家的是,开发一定不能想当然,看着没问题就不调试了,结果它就是有问题的。如果时间很紧,到了测试阶段才发现问题解决问题那就很狼狈很被动了,不要问我为什么会特别想提这个。

在写这篇文章之前,最想提醒大家的是,开发一定不能想当然,看着没问题就不调试了,结果它就是有问题的。如果时间很紧,到了测试阶段才发现问题解决问题那就很狼狈很被动了,不要问我为什么会特别想提这个。

SQL 聚合函数SUM值为NULL引发的”爆炸“。

背景

场景是这样的,一个简单的功能实现,直接以SQL语句依靠MYSQL DB直接来实现并发锁(关于锁不理解可以看这里)。语句是这样的:

update tbGift2 a, (select sum(iValue) as cnt from tbGift2 where iHostUin = '327693651' and iStatus = 1) b, (select count(*) as cnt from tbGift2 where iReceiveUin = '318713931') c set a.iStatus=1,a.iValue=2,a.iReceiveUin=3187139331, a.dtReceiveAt = now() where a.id =3 and iStatus = 0 and 8>= b.cnt+2 and 2>c.cn;

这句语句的大概意思是,要更新表数据,并且聚合sum值+2要小于等于8,count值要小于2条。咋一看,这语句没毛病吧。看起来确实也没什么问题,where条件限制了并发的发生。但是,奇怪的事情发生了,这个语句执行是不成功的!!然后代码功能就自爆了。

现场勘察

小马排查了语法,然后单独去掉8>= b.cnt+2的条件,既然执行成功了。所以这个条件很可能是false。查一下select sum(iValue) as cnt from tbGift2 where iHostUin = '327693651' and iStatus = 1语句的结果,既然是NULL。是的,你没有看错,当没有聚合记录的时候这个值就是NULL而不是0,尽管我的iValue字段是int型。NULL又如何0又如何?是的,SQL这里还有个坑,NULL是不能做比较的,只能用ISNULL,IFNULL等,用NULL作为比较的话,尽管是NULL==NULL,结果也是false。这可不是PHP哦,比较能自动转换类型。就算NULL+1=也是等于Null

解决

解决方案参考:

1、使用isnull()方法进行判断,如isnull(sum(cnt),0),其中0为默认值,如果sum(cnt)的结果为null,则赋值 0;同理此方法可用于某字段,isnull(cnt,0),这样就可以排除一些值为null的数值型字段了。而如果这样 isnull(sum(isnull(cnt,0)),0),这样就可保万无一失了。

2、使用case when else流程控制语句,如可以用"case when sum(cnt) is null then 0 else sum(cnt) end"来代替sum(cnt),其中0同上一条的意义相同。

解决后的语句:

update tbGift2 a, (select COALESCE(SUM(iValue),0) as cnt from tbGift2 where iHostUin = '327693651' and iStatus = 1) b, (select count(*) as cnt from tbGift2 where iReceiveUin = '318713931') c set a.iStatus=1,a.iValue=2,a.iReceiveUin=3187139331, a.dtReceiveAt = now() where a.id =3 and iStatus = 0 and 8>= b.cnt+2 and 2>c.cn;

执行正常。总算可以倒杯咖啡喝喝了。

image.png

别说这是我的BUG

相关文章
|
12天前
|
SQL 数据库
SQL SUM() 函数
SQL SUM() 函数
11 0
|
17天前
|
SQL
SQL NULL 值
SQL NULL 值
55 3
|
17天前
|
SQL Oracle 关系型数据库
SQL NULL 函数
SQL NULL 函数
24 1
|
23天前
|
SQL
SQL NOT NULL 约束
SQL NOT NULL 约束
21 1
|
1月前
|
SQL
SQL NOT NULL 约束
SQL NOT NULL 约束
26 6
|
1月前
|
SQL 关系型数据库 MySQL
MySQL数据库——SQL(3)-DQL(基本查询、条件查询、聚合函数、分组查询、排序查询、分页查询、案例练习)
MySQL数据库——SQL(3)-DQL(基本查询、条件查询、聚合函数、分组查询、排序查询、分页查询、案例练习)
29 0
|
2月前
|
Java
java Map删除值为null的元素
java Map删除值为null的元素
|
2月前
|
SQL 关系型数据库 数据处理
详解SQL语句中的GROUP BY和聚合函数COUNT、SUM、AVG、MIN和MAX。
详解SQL语句中的GROUP BY和聚合函数COUNT、SUM、AVG、MIN和MAX。
263 0
|
2月前
|
SQL Java 关系型数据库
JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析
JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析
71 0
|
19天前
|
SQL IDE Java
Java连接SQL Server数据库的详细操作流程
Java连接SQL Server数据库的详细操作流程