【问题标题】:How to generate a unique and random number for a primary key in sql如何在sql中为主键生成唯一的随机数
【发布时间】:2018-07-04 06:55:07
【问题描述】:

我正在处理一个要求,我需要生成一个至少 10 位的唯一(不可重复)和随机数(不可预测)。我试过 SELECT FLOOR(RAND() * 9999999).. 但不能保证唯一性。 大约每月将插入大约 20k 个值。

我还想为插入的每个条目增加一个 int 列(number_of_hits)...我正在使用 spring boot 将值插入到表中。 在创建表时尝试 number_of_hits int AUTO_INCREMENT 但后来知道这仅适用于主键.. 提前致谢!

【问题讨论】:

  • 请注意,这里的答案可能适用于也可能不适用于 H2 以外的 SQL。

标签: sql h2


【解决方案1】:

最简单的解决方案是使用UUID datatype (which can be populated automatically),并在需要时转换为 INT。

UUID 是一个 128 位整数和can be converted to BigInteger;它通常存储为十六进制值,可能看起来是一个字符串。

【讨论】:

  • 谢谢@Neville...但这给出了字母数字键..我需要一个只包含数字的键..
【解决方案2】:

使用 newid() 函数。这将创建一个 uniqueidentifier 类型的唯一值。

NEWID()
SELECT NEWID()

你可以这样使用。

INSERT INTO mytable (column1) VALUES (NEWID())

【讨论】:

  • 嗨@Tom 感谢您的回复.. 你能更具体一点,我应该在创建表格时这样做吗?抱歉(原文如此)我是 sql 新手...
  • 插入 mytable (column1) 值 (NEWID())
【解决方案3】:

我采用了以下解决方案,它也适用于数百万条记录。谢谢大家的回答。

      Calendar cal = Calendar.getInstance();
      long currentTime = cal.getTimeInMillis();
      long Max = 9999999999999L;
      long Min = 1000000000000L;
    long range = Math.abs((long) (Math.random() * (Max - Min)) + Min);
    long id = Math.addExact(currentTime, range);
    String uniqueID = createUniqueID(id);
    boolean isRepeated = urlShortenerRepository.existsByShortUrlKey(uniqueID);
    while (isRepeated) {
        range = Math.abs((long) (Math.random() * (Max - Min)) + Min);
        id = Math.addExact(currentTime, range);
        uniqueID = createUniqueID(id);
        isRepeated = urlShortenerRepository.existsByShortUrlKey(uniqueID);
    }

【讨论】:

    【解决方案4】:

    由于您选择使用 Java 代码生成唯一标识符,我想说您应该生成一个结合“唯一”部分和“随机”部分的unique identifier。请注意,您的 current answer 并不完全符合“不可预测”的要求,因为它使用了 Math.random(),这不一定是“不可预测”的 RNG。

    • “唯一”部分可以是单调递增的计数器,也可以是使用完整周期 linear congruential generator 生成的数字(在重复之前,它会伪随机地循环遍历其周期内的所有可能值)。我不建议单独使用时间戳,因为存在快速连续生成相同时间戳的风险。
    • “随机”部分只是使用加密随机数生成器生成的随机数(Java 为java.security.SecureRandom;如果可用,请使用“DRBG”实现而不是“SHA1PRNG”)。一般来说,随机部分越长,它的可预测性就越差。

    您当前的代码在正确的轨道上,但是您应该连接随机 ID 的两个部分(就像它们是字符串一样)而不是在当前时间上添加任意偏移量(例如,如果 cal.getTimeInMillis() 返回一个数字怎么办?大于Min?)。

    【讨论】:

      猜你喜欢
      • 2020-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多