【发布时间】:2022-01-12 03:57:59
【问题描述】:
我需要什么
给定一组从1 到极限n 的数字,获取最小的未被另一条记录占用的数字
详情
我的任务是将一些客户信息上传到数据库中;它需要支持遗留功能,所以我无法控制它的结构。
有一列“代码”是INT,UNIQUE,已经插入了一些数据,但它不是连续的,例如它可以有以下记录(1,2,3,5,7,125,200,500,127000)
我需要在每条新记录中插入一个尚不存在的数字,但我不想在数据中留下“漏洞”。
我不能简单地选择最大的一个并添加一个,因为最大的一个可能非常接近列的限制,而两者之间有很多可用的数字。而且我需要插入数千条记录。
例如,对于上面示例中的记录,此函数将返回“4”,因为“1”、“2”和“3”已被使用。然后,如果我使用“4”插入一条记录,它将返回“6”,因为“5”已经存在(所以请注意,我不能使用最后插入的并添加一个,因为下一个也可能被使用)...等等
我的尝试
我实际上是使用以下登录名完成的(我编写 伪代码 来简化查询,因为查询包含许多列,这使得查询非常长)
-- for each record
DECLARE i = 0
WHILE i < limit
IF (COUNT(*) FROM MyTable WHERE Code = i) = 0
INSERT INTO MyTable (Code, ...) VALUES (i, ...)
BREAK
SET i = i+1;
这行得通,但是使查询非常长并且效率不高,就好像我有 1000 次插入和从 1 到 500 的记录将循环 500000 次一样。有没有更好的方法来做到这一点?
类似INSERT INTO MyTable (Code, ...) VALUES (SMALLEST_AVALIABLE(Code), ...)
非常感谢您的宝贵时间!
【问题讨论】:
-
虽然@DaleK 是您需要的答案,但我在想您为什么要填补数据库中的漏洞?它假设您不这样做,并且是数据库上的常见行为。
-
我使用的列有一组非常有限的可用数字(大约 100 个),所以如果我想插入 80 而不使用整体,我将无法做到。谢谢@DaleK 我会看看你发送的链接。
-
为了遵循这个请求,您需要消除并发事务(查询)的基本概念。例如,您可以从其他事务中锁定该表,如果它们同时执行,这些事务可能会获得相同的值,但是由于执行此请求,您将在数据库中锁定和等待。此外,由于您在列上使用 UNIQUE,因此如果您不实现同步使用,那么在进行并发插入时可能会出错。
-
"
it needs to support legacy features so I don't have control over it's structure.":这是最常见的借口,也是大多数情况下最糟糕的借口——如果你负责系统,那么控制,如果你不在在系统上收费,然后将任务传递给他。很多时候重新设计系统就是正确的解决方案。
标签: sql sql-server tsql