【问题标题】:Generate shortest possible random unique letters-only string in a table在表中生成最短的可能随机唯一字母字符串
【发布时间】:2016-07-05 13:24:00
【问题描述】:

我在一个表中有许多记录,需要找到一种方法来分配一些唯一代码

  • 应该是唯一的;
  • 应仅包含小写字母(无数字),以便人们在电话中使用拼音字母轻松提及记录代码 - “嗨,这是约翰,我的代码是:alpha zulu 威士忌狐步舞”;
  • 应尽可能短。

记录的到期日期约为 2 周,然后将被删除。

新记录以每天数千个的速度不断创建。该表每秒获得几千次选择。

理想情况下,这应该只发生在 SQL 中,这样我就可以将它添加到“插入前”触发器中,而不是通过选择来检查数据库以检查应用程序端生成代码的唯一性,这就是我现在正在玩的东西可能会带来很大的开销,我什至不会在这里发布代码。

【问题讨论】:

  • 您能告诉我们这些代码的用途吗?
  • mysql unique number generation 的可能副本。
  • 代码用于到达呼叫中心以识别某些记录的代理。我们不希望他们必须记住或写下数字或字母数字代码。我们已经进行了测试,最好是代码仅由字母组成并尽可能短。发生这种情况的部分原因是电话线路通常很糟糕(在电话线路上拼写一个 10 个字符的字母数字代码,有噪音/延迟 => 保证烦恼和时间浪费)。本题不重复,前20-25左右搜索结果,其他所有题都指uuids或随机整数等。谢谢
  • 随机整数可以表示为以 26 为底的小写字母序列。

标签: mysql random


【解决方案1】:

将整数主键转换为以 26 为基数的数字……也就是字母。

0  becomes a
1  becomes b
25 becomes z
26 becomes aa
27 becomes ab

无需将此表示形式存储在数据库中,将其存储为整数并在显示级别将其转换为字母。

因为主键增量这不是特别安全,所以可以猜到。


如果您希望代码过期,但不希望相关数据过期,请创建第二个表来存储代码、创建时间以及返回数据的外键。使用 INSERT 触发器添加代码。

CREATE TABLE user_codes (
    code     INTEGER PRIMARY KEY AUTO_INCREMENT,
    uid      INTEGER FOREIGN KEY users(id),
    created  TIMESTAMP 
);

如上,将该整数代码转换为基数 26,其中数字都是字母。

这也保护了用户的主键,有人可能会用它做一些恶意的事情,最好不要泄露它。

这也不是特别安全,可以猜到。您可以使用the technique in this answer to pick unique random numbers 对其进行改进。


如果必须是随机且唯一的,可以考虑使用UUID_SHORT()调用生成唯一的64位数字,基本上就是时间加上一个服务器ID。然后将其转换为基数 26 并转换为字母。不幸的是,这需要大约 14 个字母。

...但是因为它是基于时间的,所以这也不是特别安全并且可以被猜到。


最后,问问自己代码是否必须是全球唯一的,或者是否足以让人们知道特定帐户的代码。比如验证码。

【讨论】:

  • Base64 表示包括数字,我们不想要数字,我们只想要数字。此外,如果我们将主键转换为基数 26,我们最终会得到一些 6 个字符,这比我们想要的要多,在任何时候我们的表中都有大约 60,000 到 100,000 条记录,所以我们不想根据主键生成我们的代码,因为代码太长了。保持代码私有不是问题,有单独的业务逻辑。 uuid_short() 返回太多字符。该代码在表中必须是唯一的,它不与帐户或任何类似的东西相关联。
  • 顺便说一句,“我们的表中有大约 60,000 到 100,000 条记录”意味着这些是可搜索的记录。我们不会在过期时将它们从表中删除,我们只是将状态字段更改为零并删除代码。将此添加为澄清,以防您建议不时重置主键以保持 ID 更短...
  • @NickM 你对 base64 是正确的......这就是为什么我从来没有提起它。至于 base 26,如果你只想使用小写字母,那是你能做的最好的事情。要涵盖 100,000 个条目,您至少需要 4 个字母 (26^4)。 Use the technique here 创建一个足够大的随机数,然后将其转换为 base 26 字母。
  • 对不起,我的意思是 base 26 不是 Base64... 错字或自动完成或两者兼而有之。谢谢。
  • @NickM 我相信你认为 base 26 必须像十六进制、0-9 那样完成,然后是额外的 16 位数字。相反,放弃数字,只使用 a-z 作为数字。 (我意识到我在我的例子中留下了 0 并且我已经修复了它)
猜你喜欢
  • 2011-08-18
  • 1970-01-01
  • 1970-01-01
  • 2013-10-14
  • 2012-11-21
  • 2010-10-18
  • 2020-08-11
  • 2017-02-21
相关资源
最近更新 更多