CoffeeCat's IT Blog

浅谈SQL Update返回影响行数的意义

在大学的时候学习了JSP,其中使用JDBC进行数据库操作,有一个语句是Statement.ExecuteUpdate,这个语句执行一个SQL的更新操作(如delete,update,insert),返回所影响的行数。当返回0时,则表示没有更新任何行。我以为可以判断返回值是否大于0来判断更新是否成功,但是,下面的两种情况均返回0:

    1:没有找到需要更新的数据
       比如,我们进行update的时候,条件是id=5,但是id=5的数据不存在。这种情况下,更新是失败的,返回0,很正确。

    2:要更新的数据和更新的值是完全一样的
       比如,我们要对id=5的记录进行更新,把title变成hello。虽然这条记录存在,但是这条记录的title本来就是hello,那么,返回值也是0

 

这样就有个问题,当第2种情况发生时,从逻辑上讲,更新操作是成功的,你可以理解成title被重新覆盖了,不管它原来是不是hello,但是现在就被更新成hello了。

因此,如果要对Update进行是否更新成功的判断,就需要在Update之前,调用Statement.ExecuteQuery进行查询,如果能查询到记录,则表示更新会成功。ExecuteUpdate的返回值仅仅代表更新了多少行。

这样,一个Update操作就会执行2次SQL语句的,效率会降低。我当时就纳闷,为什么ExecuteUpdate对于第2种情况会不返回0,虽然从数据库的角度上,它是可以忽略更新这条记录,但是从逻辑的角度上看,这条记录被更新似乎更加合乎情理,返回大于0的值似乎更有意义。


不过,为什么基本上所有的编程语言,只要有类似的函数,都会在第2种情况返回0呢?


最近,这个问题总算想通了,之所以返回0,其实是为了解决同步的问题。

举个例子,现在,著名的开心网要对菜园的功能进行扩展,不光是能让玩家种菜,还要能让玩家偷别人家的菜。我们的程序逻辑如下:

 

某菜园:有成熟的菜N颗
A:     有偷来的菜0颗
===========================
A:     某菜园有多少颗成熟的菜?
某菜园:N
A:     偷1颗
某菜园:成熟的菜=N-1

A:     口袋里的菜
+1
===========================
某菜园:有成熟的菜N-1颗
A:     有偷来的菜1颗  

 

 

这段程序的逻辑没有任何问题。

好了,现在程序开始给玩家用了,有一颗超级无敌白金大青菜快成熟了,众玩家垂涎欲滴等着偷。成熟的那一刻,众玩家以瞬间的爆发力点击了鼠标左键,进行了偷菜。

假设有2个人A和B,几乎同时点击了鼠标,我们看服务器上程序的逻辑:


 

某菜园:有成熟的菜N颗
A:     有偷来的菜0颗
B:     有偷来的菜0颗

===========================
A:     某菜园有多少颗成熟的菜?
B:     某菜园有多少颗成熟的菜?
某菜园:N
某菜园:N
A:     偷过来
B:     偷过来
某菜园:成熟的菜=N-1

某菜园:成熟的菜=N-1

A:     口袋里的菜
+1
A:     口袋里的菜
+1
===========================
某菜园:有成熟的菜
N-1
A:     有偷来的菜1颗  
B:     有偷来的菜1颗  

 

 

大家可以看到,现在的超级无敌白金大青菜总数变成了N+1了,无故多出了1颗,显然,这个结果是不对的,也不是我们想要的。

开心网的代码是用PHP开发的,PHP中可没有Java中的Synchronous关键字。如果用一个本地文件来实现锁的功能,服务器的运行效率就会大大打折。那么,我们如何高效的解决这个同步问题呢?这时候,执行Update返回所影响的行数就具有了超人般的意义了。


 请看上面第2段中的粗体代码,在执行这个逻辑的时候,我们会得到的Update的返回值是0,因为在做这个操作之前,菜园里的蔬菜数量已经被更新成N-1了,所以这个更新操作会被忽略,这样,我们就可以在程序中加一个判断:如果更新的返回值是0,则表示偷菜失败,虽然Update是成功的。虽然B问菜园的时候是有菜的,但是偷的时候却没有了,那也表示B没有偷到。

可见,返回所影响的行数是非常有意义的,对于并发量大的网站,可以好好利用这个返回值,能在保证效率的状态下,解决同步的问题。



Ferris
2009-05-04

posted on 2009-05-04 18:30 CoffeeCat 阅读(9176) 评论(1)  编辑 收藏 引用

评论

# re: 浅谈SQL Update返回影响行数的意义 2012-10-26 15:36 bloodynumen

谢谢  回复  更多评论   

只有注册用户登录后才能发表评论。
<2011年8月>
31123456
78910111213
14151617181920
21222324252627
28293031123
45678910

导航

统计

公告

常用链接

留言簿(203)

随笔档案

收藏夹

搜索

最新评论

阅读排行榜

评论排行榜