在SQL Server数据库的非IDENTITY类型字段中重新分配ID

com*_*ill 7 sql sql-server sql-server-2008r2-express

警告:这个悲惨的故事包含代码气味和糟糕的设计决策以及技术债务的例子.

如果您熟悉SOLID原则,请练习TDD并对您的工作进行单元测试,请勿阅读.除非你想要对某人的不幸进行一次好的傻笑,并且在你自己很棒的事情中幸灾乐祸地知道你永远不会为你的继任者留下如此巨大的废话.

所以,如果你坐得舒服,我会开始.

在这个应用程序中,我已经继承并一直支持和修复过去7个月的错误,我被一个开发人员留下了6个半月之前留下了一大堆.是的,我开始后2周.

无论如何.在这个程序,我们有clients,employeesvisits表.

还有一个名为AppNewRef(或类似的东西)的表......等待它...包含用于其他每个表的下一个记录ID.因此,可能包含以下数据: -

TypeID    Description     NextRef
   1      Employees       804
   2      Clients         1708
   3      Visits          56783
Run Code Online (Sandbox Code Playgroud)

当应用程序为其创建新行时Employees,它会在AppNewRef表中查找,获取值,使用该值作为ID,然后更新NextRef列.同样的事情Clients,以及Visits所有其他NextID使用的表存储在这里.

是的,我知道,IDENTITY这个数据库上没有自动编号列.所有这些都是"当它是一个Access应用程序"的借口.这些ID保存在(VB6)代码中.因此,可能有多达20亿1.47亿条记录.好的,这似乎运作得相当好.(除了应用程序正在更新和处理锁定/更新等事实,而不是数据库)

因此,我们的用户是很愉快地创造Employees,Clients,VisitsVisits ID稳定地逐渐增加了几十个.然后问题就发生了.我们的客户在创建批量访问时会导致数据库损坏,因为服务器很好地丢失了,应用程序变得没有响应.因此,他们使用任务管理器杀死应用程序,而不是耐心等待.当然,该应用似乎确实锁定了.

转到今年早些时候,开发人员蒂姆(真实姓名.没有保护有罪的人)开始修改代码以分阶段进行批量更新,以便UI保持"响应".然后四月来了,他正在做他的通知(你现在可以想象现场,不是吗?)他正在努力完成更新.

4月底,5月初我们更新了一些客户.在接下来的几个月里,我们会越来越多地更新它们.

蒂姆(真名,记得)和我(在蒂姆离开前两周开始)以及一周后开始的另一位新开发者看不见,访问表中的ID开始向上跳跃.巨大的,我的意思是10000,20000,30000一次.有时几十万.

这是一个图表,说明了使用的ID的快速增长.

看看他的图表

11月滚.客户致电技术支持并报告他收到了错误消息.我查看错误消息并询问数据库,以便我可以调试代码.我发现这个值太大了很长时间.我做了一些查询,提取信息,将其放入Excel并绘制图形.

我不认为使代码处理的时间长于ID,这是正确的方法,因为这个应用程序将该ID传递给其他DLL和OCX,并打破那些看起来像是一个整个世界的伤害我不喜欢我现在想要遇到.

我正在研究的一个潜在想法是尝试修改ID,以便我可以将它们降低到更低的水平.基本上填补了空白.使用该ROW_NUMBER功能

我正在考虑做的是为每个表添加一个新列,这些表具有对这些访问ID的外键引用(不是正确的外键思维,这个数据库中不存在这些约束).这个新列可以存储访问ID的旧(当前)值(哦,只是为了混淆事情;在某些表上调用它EventID,以及在某些表上调用它VisitID).

然后,对于引用它的每个其他表VisitID,更新为新值.

想法?建议?T-SQL的片段帮助所有人感激不尽.

chr*_*ie1 1

我会创建一个数字表,其中只有一个从 1 到任何最大值的序列,增量为 1 很长,然后更改获取访问 ID 的 maxid 的逻辑,也许其他人在数字和访问表之间进行正确的连接。然后你就可以查找该数字的最小值

select min(number) from visits right join numbers on visits.id = numbers.number
Run Code Online (Sandbox Code Playgroud)

这样您就可以填补所有空白,而无需更改任何其他表。

但我只想重做整个数据库。