2

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

背景资料

我有一个小部件表。每个小部件都从一系列数字中分配了一个 ID,比如说 1-999。1-999 的值在我的数据库中保存为名为“config”的表中的“lower_range”和“upper_range”。当用户请求使用我的网络应用程序创建新的小部件时,我需要能够执行以下操作:

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

问题

我在上述逻辑中看到的问题有两个:

  1. 该算法可能需要很长时间,因为我必须继续搜索,直到找到唯一值。
  2. 如何防止同时请求生成相同值的新小部件编号?

任何建议,将不胜感激。谢谢

4

5 回答 5

2

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

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

做这个:

  • 以某种随机顺序生成具有 1-999 值的 999 个元素的数组
  • 你的GetNextId功能变成return ids[currentMaxId+1]

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

于 2013-05-08T18:20:05.190 回答
1

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

例如,制作一个 1 - 999 的数字列表。使用Fisher-Yates或等效方法对该列表进行随机排序(另请参阅在 C# 中随机化列表,即使您不使用 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
于 2013-05-08T18:16:35.093 回答
1

创建一个表来存储键和“使用”属性。

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

然后使用以下内容找到一个新密钥

select id
from KEYS
where used = 0
order by RANDOM()
limit 1
于 2013-05-08T18:15:16.567 回答
0

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

替换为 random_sequence 值 ((select id from random_sequence where used=0 order by random()), 1);

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

当您用完“未使用”的序列表条目时,选择将返回“空白”

我使用 replace into 因为更新没有我可以看到的 last_insert_rowid() equiv。

于 2013-05-08T21:07:44.793 回答
-2

您可以让 sql 创建一个主键,每次您将 ros 添加到数据库时,主键都会增加一个。

于 2013-05-08T18:04:15.683 回答