SQL的update语句更新顺序的坑

文章目录

环境

  • Windows 11 专业版
  • XAMPP v3.3.0
    • MySQL Ver 15.1
  • MySQL Workbench 8.0 CE

背景

t1 中有三列 c1c2c3

  • c1 :总名额
  • c2 :已报名数量
  • c3 :替补名额

其中,"总名额"包含了"替补名额"。比如,一场比赛A(id为1)的正式名额是14,而总名额是20,其中包含了6个替补名额。到报名截止时间,实际报名数量是18人。也就是说:

  • c1 = 20
  • c2 = 18
  • c3 = 6

t1 如下:

在比赛开始前,需要处理替补人员。对于本例,只有14个正式名额,因此需要把4个替补人员劝退( c2 会变成14)。

接下来,需要把替补名额修改为0,并把总名额修改为14。

SQL

从上面的需求可知,对于"把替补名额修改为0,并把总名额修改为14",只需要一个update语句,把 c3 清零,并把 c1 改为 c1 - c3

sql 复制代码
update t1 set c3 = 0, c1 = c1 - c3 where id = 1;

看上去没有问题,然而,运行SQL后,表 t1 内容如下:

可见, c1 的值没有变化!

这是因为,update语句在更新数据时,按照"从左到右"的顺序依次更新,并且使用的是"最新的值"。

也就是说,我们期望把 c1 修改为 c1 - c3 ,也就是 20 - 6 ,值为 14 ,然而,在此操作之前, c3 已经被清零了,所以, c1 的值实际上并没有发生变化。

这个问题让我困惑了半天,我一直以为是我把SQL语句哪里写错了(因为我使用了ThinkPHP框架,没有用原生SQL),后来才醒悟过来,是我对SQL的语义理解有偏差。

知道了问题产生的原因,那么问题也就迎刃而解了。

最简单的解决办法,就是交换一下更新的顺序:

sql 复制代码
update t1 set c1 = c1 - c3, c3 = 0 where id = 1;

这样, c1c3 都能得到期望值了。

总结

update语句在更新数据时,按照"从左到右"的顺序依次更新,并且使用的是"最新的值",所以一定要小心顺序,别搞错了。

相关推荐
倔强的石头_8 小时前
《Kingbase护城河》——数据库存储空间全景探测与精细化瘦身实战
数据库
云技纵横9 小时前
唯一索引 INSERT 死锁实战:5 秒复现交叉插入的 S 锁循环等待
sql·mysql
沉默王二9 小时前
面试官:RAG 不用向量数据库,用 MySQL 硬扛?我:100 万向量不是很轻松?
mysql·面试·ai编程
冬奇Lab21 小时前
每日一个开源项目(第134篇):Zvec - 阿里开源的嵌入式向量数据库,向量搜索界的 SQLite
数据库·人工智能·llm
小猿姐1 天前
MySQL Top 10 热点问题 AI 运维实战:从内核诊断到云原生运维
mysql·云原生·aiops
ClouGence1 天前
Oracle CDC 架构优化:从主库直连到 DataGuard 备库同步
数据库·后端·oracle
云技纵横1 天前
Gap Lock 死锁实战:5 秒在本地复现 MySQL 间隙锁死锁
后端·mysql
无响应de神1 天前
三、用户与权限管理
数据库·mysql
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql