Как сгенерировать уникальное и случайное число для первичного ключа в SQL - PullRequest
0 голосов
/ 04 июля 2018

Я работаю над требованием, при котором мне нужно сгенерировать уникальное (не повторяемое) и случайное число (непредсказуемое) с как минимум 10 цифрами. Я пытался SELECT FLOOR (RAND () * 9999999) .., но с этим нельзя гарантировать уникальность. В месяц будет вставлено около 20 тыс. Значений.

Также я хочу увеличить столбец int моей таблицы (number_of_hits) для каждой вставленной записи ... Я использую весеннюю загрузку для вставки значений в таблицу. Пробовал number_of_hits int AUTO_INCREMENT при создании таблицы, но позже узнал, что это будет работать только на первичном ключе. Заранее спасибо.!

Ответы [ 4 ]

0 голосов
/ 14 мая 2019

Поскольку вы решили использовать код Java для генерации уникального идентификатора, я хочу сказать, что вы должны сгенерировать уникальный идентификатор , который объединяет «уникальную» часть и «случайную» часть. Обратите внимание, что ваш текущий ответ не совсем соответствует «непредсказуемому» требованию, поскольку в нем используется Math.random(), который не обязательно является «непредсказуемым» ГСЧ.

  • «Уникальная» часть может быть монотонно увеличивающимся счетчиком, или это может быть число, сгенерированное с полным периодом линейный конгруэнтный генератор (который повторяет псевдослучайно все возможные значения в своем периоде перед повторением) , Я не рекомендую использовать только временные метки, поскольку существует риск генерирования одной и той же временной метки в быстрой последовательности.
  • «Случайная» часть - это просто случайное число, сгенерированное с помощью криптографического генератора случайных чисел (для Java это java.security.SecureRandom; используйте реализацию «DRBG» вместо «SHA1PRNG», если доступно). Как правило, чем длиннее случайная часть, тем менее предсказуемой она будет.

Ваш текущий код находится на правильном пути, но вы должны объединить две части случайного идентификатора (как они были строками), а не добавлять произвольное смещение к текущему времени (например, что если cal.getTimeInMillis() возвращает число больше чем Min?).

0 голосов
/ 04 июля 2018

Самое простое решение - использовать UUID-тип данных (который может быть заполнен автоматически) и преобразовать его в INT, когда вам это нужно.

UUID представляет собой 128-разрядное целое число, а может быть преобразовано в BigInteger ; обычно он хранится в виде шестнадцатеричного значения, которое может выглядеть как строка.

0 голосов
/ 05 июля 2018

Я воспользовался приведенным ниже решением, и оно отлично работает и с миллионами записей. Спасибо всем за ответы.

      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);
    }
0 голосов
/ 04 июля 2018

Используйте функцию newid (). Это создаст уникальное значение типа uniqueidentifier.

NEWID()
SELECT NEWID()

Вы можете использовать вот так.

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