SQL表数据更新异常求助:末尾数据移至开头后重复
问题根源拆解
兄弟,你这问题我太熟了!核心原因就是你的UPDATE语句里,目标行(ID1-3566)和要拿来更新的源行(ID3567-7243)之间没有建立精准的对应关系。
当你写UPDATE ... FROM (SELECT ... WHERE Id BETWEEN 3567 AND 7243) dt WHERE Id BETWEEN 1 AND 3566时,数据库会把每个目标行和子查询里的所有源行做匹配——但你没告诉它“目标行1对应源行3567,目标行2对应源行3568”这种规则,数据库就会偷懒,随便选子查询里的一行(通常是第一条也就是ID3567的记录)来更新所有目标行,结果自然就是全变成3567的数据了。
正确的解决思路:给行打序号做匹配
要实现把后面的记录依次移到前面,咱们得给两组行分别生成连续的序号,让第N条源行对应第N条目标行。用ROW_NUMBER()窗口函数就能轻松搞定,看下面的代码:
WITH SourceRows AS ( SELECT Xwgs, Ywgs, -- 给3567-7243的记录按ID升序排,生成从1开始的序号 ROW_NUMBER() OVER (ORDER BY Id ASC) AS RowNum FROM dbo.TABLE WHERE Id BETWEEN 3567 AND 7243 ), TargetRows AS ( SELECT Id, -- 给1-3566的记录按ID升序排,生成从1开始的序号 ROW_NUMBER() OVER (ORDER BY Id ASC) AS RowNum FROM dbo.TABLE WHERE Id BETWEEN 1 AND 3566 ) UPDATE t SET t.Xwgs = s.Xwgs, t.Ywgs = s.Ywgs FROM dbo.TABLE t JOIN TargetRows tr ON t.Id = tr.Id JOIN SourceRows s ON tr.RowNum = s.RowNum;
为啥这么写?
SourceRows:把你要挪的那批数据(3567-7243)按ID从小到大排,给每一行标上1、2、3...的序号,这样最前面的源行(3567)对应序号1,下一个(3568)对应序号2,以此类推。TargetRows:给要被替换的目标行(1-3566)也按ID从小到大标上1、2、3...的序号,目标行1对应序号1,目标行2对应序号2。- 最后通过
RowNum这个序号把两组行精准关联起来,实现“第1条源行更新第1条目标行,第2条源行更新第2条目标行”的效果。
安全提示!
执行UPDATE前一定要先验证关联是否正确,别直接就更了!可以先跑下面的查询看看对应关系对不对:
SELECT tr.Id AS 目标ID, s.Id AS 源ID, s.Xwgs, s.Ywgs FROM TargetRows tr JOIN SourceRows s ON tr.RowNum = s.RowNum;
确认每一行目标ID都对应了正确的源ID,再执行UPDATE就稳了。
内容的提问来源于stack exchange,提问作者mobdev
相关产品推荐
相关产品推荐

