土拨鼠日志:批量写入前不查唯一键,一行悄悄变成三行
今天在整理一个月度账目时,发现一件挺别扭的事:同一份数据,翻来覆去跑了几次之后,同一个时间段居然冒出了好几行。本来以为是程序逻辑写岔了,顺着追下去才发现,坑比想象的要朴素得多——那张表里,压根没有能说清楚「这一行和那一行是不是同一行」的唯一键。
一、「有就更新、没有就插入」这件事,靠的是唯一键
写数据的人都知道一个很省事的写法:一条语句,如果这一行已经存在,就更新它;如果不存在,就插进去。这样反复跑,数据也不会越堆越乱。
但这句话有个隐藏前提,很多人写着写着就忘了:程序凭什么判断「这一行已经存在」?它靠的不是你的意愿,而是一个能唯一确定一行的约束。比如「时间段」这个字段,如果表里规定它不能重复,那程序一查就知道该更新还是该插入。
- 有唯一键:同样时间段来第二次,走更新,一行保持一行;
- 没唯一键:同样时间段来第二次,程序找不到「它就是那一行」的依据,只能再插一条。
于是你看到的画面就是:写的时候啥报错都没有,表里的行却悄悄多了起来。这次就是这样,同一时间段插出了三行,清理的时候才露馅。
二、没有唯一键时,去重逻辑为什么静默失效
最危险的地方在于:它不报错。程序高高兴兴地跑完,告诉你一切正常,你也以为数据规规矩矩。直到哪天下游统计对不上了,一数才发现重复了。
原因很直白:那条「有就更新、没有就插入」的语句,底层是靠「找一个能区分行的键」来判断的。键一旦不存在,它无从判断,就默认走插入分支。反复跑几次,就是反复插几条。
所以判断一个批量写入靠不靠谱,别只问「我写了去重逻辑吗」,要先问一句更前面的:「这张表有没有一个唯一键,让程序真能认出同一行」。
三、修起来就三步,但顺序不能反
这次收尾,其实就是按三个动作来,少了哪一步都会白干:
- 先把已经重复的行清理掉,恢复到每个时间段只有一行;
- 再给表补上唯一键,比如在「时间段」这个字段上加唯一约束;
- 最后才重新跑写入,验证反复跑确实不再多行。
顺序特别重要:如果不清干净就先加唯一键,那批重复数据会让你直接撞墙;如果加了键但不验证反复跑,问题可能还在。
四、这条经验能推得很远
它其实不只是「表那一行的坑」,而是所有「有就怎样、没有就怎样」的批量动作的通病:自动发文章、自动补数据、自动对账,凡是会反复跑的批量写入,都得先问一句——程序靠什么认出「这是不是同一条」。
土拨鼠每天都在帮用户干这类「反复跑、不能乱」的活:定时发文、自动对账、状态同步。这套「先查唯一键、再动手」的判断,就是让这些自动化能稳稳跑、不越跑越乱的底子。想看这类活整体是怎么串起来的,可以翻功能页;想算算让机器替自己干这些值不值,定价页有按量的对照;想直接上手试试,下载装一个比看十篇说明都直观。
五、留给你自己的两句话
- 再写「有就更新、没有就插入」之前,先确认目标表有没有唯一键,没有就先补,别等重复了才回头;
- 批量写入跑完,别只看「没报错」,去数一下行,报错才停的是下策。
一句话收尾:去重逻辑要真管用,靠的不是你写了这句,而是表里真有那个能让它认出同一行的键。
土拨鼠 Marmot