我在这个问题上失败了好几个小时了,只是无法理解它。从“人类”POV看起来相当简单,但不知怎的,我似乎无法将其写入代码。
情况:给出几个由起始编号和当前“活动”编号定义的编号范围,这些编号分配给特定位置(或0表示通用编号)
startno | actualno | location
100 | 159 | 0
200 | 203 | 1
300 | 341 | 2
400 | 402 | 0
现在,正如您所看到的,一个位置也可以有两个范围。在这种情况下,只有具有最高startno的范围(在这种情况下,400)被视为活动,另一个仅用于历史目的。
每个用户都被分配到一个特定的位置(与位置列中的ID相同),但从不分配给通用位置(零)。
当一个用户想要一个新号码时,他将从一个分配给他所在位置的范围中获得一个号码,或者,如果没有找到,则从最高一般号码中获得一个号码(例如,user.location = 0将获得403, user.location = 2会得到342)。
然后,用户可以选择从指定的号码开始使用此号码或金额X.
问题在于:我如何确保范围不会相互重叠?假设用户(位置= 2)获得下一个数字342并确定他之后需要100个数字。这将产生441的结束号,这是在通用范围内,这是不可能发生的。
我尝试了几个嵌套的SELECT,使用起始和结束数字,聚合MAX(),将表连接到自身,但我无法100%正确。
答案 0 :(得分:0)
根据我对这样的事情的理解,我可能只是在db中的表上创建一个触发器来进行验证,并在应用程序更新表时发现重叠时引发错误,这样用户只会得到一个错误说你做不到。假如你想让它以441结尾然后让用户这样做并尝试用 actualno 更新表到441,然后一个简单的选择将新数字与所有现有 startno 看看它是否比任何 startno 更大,然后引发错误。在更新触发器中跟随以下内容:
IF EXISTS(SELECT 1 FROM
Table1
WHERE @newnumber >= startno AND id <> @currentID)
BEGIN
'Go Raise the error
END
好吧,也许我在某些情况下错过了一些不合适的东西,请告诉我。
使用触发器进行数据完整性检查是完全可以的,根本不应该是一个问题。这比未来的验证要容易得多,特别是如果你考虑多线程的东西可能会在那里产生一些大问题。
另一方面,为了防止这种情况发生得太容易,我可能会在这些数字中添加几个零作为初始值:
startno | actualno | location
100000 | 100059 | 0
200000 | 200003 | 1
300000 | 300041 | 2
400000 | 400002 | 0
答案 1 :(得分:0)
经常这样,我在发布问题后不久就找到了一种方法。它似乎描述了一个问题,所以其他人都明白它是获得解决方案的一半。至少,我得到了一个迄今为止证明非常具有抵抗力的可能。
我用
查询数据库SELECT nostart FROM numbers
WHERE nostart BETWEEN X AND Y
其中X
是请求的起始编号,Y
是用户的结束编号。 (为了符合我的介绍示例,X = 342
和Y = 441
然后,这将为我提供一个列表,其中包含起始编号在用户请求的编号范围内的所有范围,在这种情况下,列表将是
nostart
400
现在,如果查询没有找到结果,我就是金色的,可以使用这些数字。如果查询找到一个结果,并且该结果等于用户的起始编号,我也没问题,因为这意味着这是用户第一次请求此范围内的内容。
如果不是这种情况,则无法使用范围,因为其中包含另一个范围。此外,如果查询找到多个结果(例如,对于X = 100
和Y = 350
,这将导致100|200|300
我也拒绝该请求,因为多个范围重叠。
如果有人在这个问题上有更好的解决方案或说明,我会把它留在这里并使用它,只要它能够解决。