为表中的主键随机生成介于1-999之间的唯一编号

时间:2013-05-08 17:59:53

标签: sql sqlite lua

我有一个问题我不确定如何优雅地解决。

背景资料

我有一个小工具表。每个小部件都分配了一系列数字的ID,假设在1-999之间。值1-999在我的数据库中保存为" lower_range"和" upper_range"在一个名为" config"的表中。 当用户使用我的Web应用程序请求创建新窗口小部件时,我需要能够执行以下操作:

  • 使用lua的math.random函数或sqlite中的随机数生成器生成1到999之间的随机数(到目前为止,在我的测试中,lua' s math.random总是返回相同的值......但那是一个不同的问题)
  • 执行一个select语句,看看是否已经分配了这个号码的小部件......
  • 如果没有,请创建新小部件。
  • 否则重复处理,直到您获得当前未使用的号码。

问题

我在上述逻辑中看到的问题是双重的:

  1. 算法可能需要很长时间,因为我必须继续搜索,直到找到唯一值。
  2. 如何防止同时请求生成相同值的新窗口小部件编号?
  3. 任何建议将不胜感激。 感谢

5 个答案:

答案 0 :(得分:2)

提前生成随机数并将其存储在表格中;确保数字是唯一的。然后,当您需要获取下一个号码时,只需检查已分配的号码并从表中获取下一个号码。所以,而不是

  • 生成1-999
  • 之间的数字
  • 检查是否已分配
  • 生成新号码,依此类推。

这样做:

  • 生成999个元素的数组,这些元素的值为1-999,以某种随机顺序
  • 您的GetNextId函数变为return ids[currentMaxId+1]

要管理同步请求,您需要拥有一些生成正确序列的资源。最简单的可能是使用窗口小部件表中的键作为ids数组中的索引。因此,首先在widgets表中添加记录,获取其密钥,然后使用ids[key]生成窗口小部件ID。

答案 1 :(得分:1)

创建一个表来存储密钥和'used'属性。

CREATE TABLE KEYS
  ("id" INTEGER, "used" INTEGER)
;

然后使用以下命令查找新密钥

select id
from KEYS
where used = 0
order by RANDOM()
limit 1

答案 2 :(得分:1)

不要生成随机数,只需从随机顺序列表中选择数字。

例如,制作一个数字列表1 - 999.使用Fisher-Yates或同等数据对该列表进行随机播放(即使您没有使用C#,也请参阅Randomize a List in C#。)

现在,您可以在列表中跟踪最近使用的索引。 (对列表进行洗牌应该只发生一次,然后存储并重用结果)。

粗糙的伪代码:

If config-file does not contain list of indices
    create a list with numbers 1 - 999
    Use Fisher-Yates to shuffle that list
    // list now looks like 0, 97, 251, 3, ...
    Write the list to the config file
    Set 'last index used' to 0 and write to config file
end if

要使用它,

NextPK = myList[last-index-used]
last-index-used = last-index-used + 1
write last-index-used to config file

答案 3 :(得分:0)

获取并标记同时使用的ID(扩展Declan_K的答案):

替换为random_sequence值((从random_sequence中选择id,其中使用= 0 by random()),1);

从random_sequence中选择id,其中rowid = last_insert_rowid(); 6

当您用完“未使用”的序列表条目时,select将返回“blank”

我使用replace into,因为update没有last_insert_rowid()等于我可以看到。

答案 4 :(得分:-2)

你可以让sql创建一个主键,这会增加你向数据库添加一个ros的一次。