Генерация уникальной и случайной кодовой цифры с MySQL - PullRequest
3 голосов
/ 09 марта 2012

Начальная цель:

Я хотел бы генерировать случайные и уникальные коды (6 цифр) в таблице.Для этого я использую SQL-запрос, подобный этому:

SELECT SUBSTRING(CRC32(RAND()), 1, 6) as myCode
FROM `codes`
HAVING myCode NOT IN (SELECT code FROM `codes`)

Я спросил меня, как он будет реагировать, когда больше не будет доступных кодов, поэтому я делаю следующий тест


Контекст теста:

Версия MySQL: 5.5.20

Таблица MySQL:

CREATE TABLE `codes` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`code` VARCHAR( 10 ) NOT NULL ,
UNIQUE (
`code`
)
) ENGINE = InnoDB;

Исходные данные:

INSERT INTO `codes` (`id`, `code`)
VALUES (NULL, '1'), (NULL, '2'), (NULL, '3'), (NULL, '4'), (NULL, '5'), (NULL, '6'), (NULL, '7'), (NULL, '8');

Запрос SQL:

SELECT SUBSTRING(CRC32(RAND()), 1, 1) as myCode
FROM `codes`
HAVING myCode NOT IN (SELECT code FROM `codes`)

При выполнении этого запроса я ожидаю, что он всегда будет возвращать 9, поскольку это единственный код одной цифры, который не существует.

Но результат таков:

  • Иногда он возвращает строки
  • Иногда возвращает строки с уже существующими значениями

Я не понимаю этогоповедение, так что если кто-то может помочь:)

Так что большой вопрос:

Как MySQL может возвращать строки с уже существующими значениями?

Спасибо

1 Ответ

2 голосов
/ 09 марта 2012

Я бы заполнил таблицу sequencetable всеми возможными значениями в последовательности.

Затем случайный запрос просто случайным образом выбирает записи из sequencetable и каждый раз, когда он выбирает запись, удаляет ее. Таким образом, вы обязательно получите все номера, не теряя времени на поиск номера «дыры» (еще не подобранного).

CREATE TABLE `sequencetable` 
(
    `sequence` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence`)
)
ENGINE=InnoDB
AUTO_INCREMENT=1;

Заполните последовательность (на самом деле нет необходимости в AUTOINCREMENT).

DECLARE i INT;

SET i=1;
REPEAT
    INSERT INTO sequencetable VALUES (i);
    SET i=i+1;
UNTIL i>999999 END REPEAT;

Выберите случайную запись из последовательности (делайте это в цикле, пока записи не станут доступны):

DECLARE sequencen INT;

SET sequencen = 
    (SELECT sequence FROM sequencetable ORDER BY RAND() LIMIT  1);

DELETE FROM sequencetable WHERE sequence = sequencen;
...