Подтвердить что ты не робот

Как создать уникальную случайную строку для одного из столбцов таблицы MySql?

Im, используя MySql 5.5.37. У меня есть таблица со следующими столбцами

+------------------+------------------+------+-----+---------+-------+
| Field            | Type             | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+-------+
| ID               | varchar(32)      | NO   | PRI | NULL    |       |
| CODE             | varchar(6)       | NO   | UNI | NULL    |       |

Колонка кода уникальна, а мой идентификатор - GUID. У меня есть ряд строк, которые я бы хотел обновить, с учетом некоторых критериев в приведенной выше таблице (например, WHERE COLUMN1 = 0). Как создать случайные, уникальные 6-символьные коды (идеально буквы и цифры) для моего столбца CODE, чтобы они не нарушали уникальное ограничение в моей таблице? Обратите внимание, что столбцы в таблице, которые не соответствуют критериям (например, где COLUMN1 < > 0) уже имеют уникальные значения для столбца CODE.

Изменить: Это отличается от этого вопроса - Создание случайной и уникальной 8-символьной строки с использованием MySQL, потому что эта ссылка связана с идентификаторами taht являются числовыми. Мои идентификаторы - 32-символьные строки. Также их решение не учитывает тот факт, что в таблице могут быть значения перед запуском операторов, которые я хочу запустить, которые будут генерировать уникальные значения для рассматриваемого столбца.

4b9b3361

Ответ 1

ДОПОЛНИТЕЛЬНОЕ решение:

Вы можете создать произвольную буквенно-цифровую строку в верхнем регистре с 6 символами:

lpad(conv(floor(rand()*pow(36,6)), 10, 36), 6, 0);

Чтобы не создавать уже существующую строку, вы можете использовать триггер BEFORE UPDATE.

DELIMITER //
CREATE TRIGGER `unique_codes_before_update`
BEFORE UPDATE ON `unique_codes` FOR EACH ROW 
BEGIN
    declare ready int default 0;
    declare rnd_str text;
    if new.CODE is null then
        while not ready do
            set rnd_str := lpad(conv(floor(rand()*pow(36,6)), 10, 36), 6, 0);
            if not exists (select * from unique_codes where CODE = rnd_str) then
                set new.CODE = rnd_str;
                set ready := 1;
            end if;
        end while;
    end if;
END//
DELIMITER ;

Каждый раз, когда вы устанавливаете столбец CODE в NULL в инструкции UPDATE, триггер создаст новую случайную строку в цикле, пока в таблице не будет найдено совпадения.

Теперь вы можете заменить все значения NULL на:

update unique_codes set CODE = NULL where code is NULL;

В демоверсии SQLFiddle здесь я использую случайную строку из одного символа, чтобы продемонстрировать, что никакое значение не дублируется.

Вы также можете использовать тот же код в триггере BEFORE INSERT. Таким образом, вы можете просто вставить новые строки с помощью CODE=NULL, и триггер установит его в новую уникальную случайную строку. И вам больше не понадобится обновлять его.

Оригинальный ответ (32 символьные строки):

select lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0) as rnd_str_8;

-- output example: 3AHX44TF

будет генерировать 8-значную буквенно-цифровую случайную строку в верхнем регистре. Объедините четыре из них, чтобы получить 32 символа:

select concat(
    lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0),
    lpad(conv(floor(rand()*pow(36,8)), 10, 36), 8, 0)
) as rnd_str_32;

-- output example: KGC8A8EGKE7E4MGD4M09U9YWXVF6VDDS

http://sqlfiddle.com/#!9/9eecb7d/76933

А как насчет унификации? Хорошо - попытайтесь создать дубликаты; -)

Ответ 2

Это сложно, но я думаю, что достиг хорошего решения:

DROP FUNCTION IF EXISTS getRandomAlphaNumeric;

DELIMITER $$

CREATE FUNCTION getRandomAlphaNumeric() RETURNS CHAR(6)
DETERMINISTIC
BEGIN

    SELECT 
    CONCAT (
        CHAR(FLOOR(RAND()*10)+48), CHAR(FLOOR(RAND()*26)+65), CHAR(FLOOR(RAND()*26)+97),
        CHAR(FLOOR(RAND()*10)+48), CHAR(FLOOR(RAND()*26)+65), CHAR(FLOOR(RAND()*26)+97)
    ) INTO @code
    ;

    RETURN @code;
END
$$

DELIMITER ;


DROP PROCEDURE IF EXISTS generateCodes;

DELIMITER $$
CREATE PROCEDURE generateCodes()
BEGIN

    SET @count = 0;
    SELECT COUNT(1) INTO @count FROM demo.codes;

    SET @i = 0;
    WHILE @i < @count DO

        PREPARE stmt FROM "SELECT @id := id, @itemCode := code FROM demo.codes p LIMIT ?, 1;";
        EXECUTE stmt USING @i;

        SET @code = getRandomAlphaNumeric();

        SELECT COUNT(1) INTO @countRowsWithCode FROM demo.codes WHERE code = @code;

        IF @countRowsWithCode = 0 AND @itemCode IS NULL THEN
            UPDATE demo.codes SET code = @code WHERE id = @id;
        END IF;

        SET @i := @i + 1;   
    END WHILE;
END
$$

DELIMITER ;


CALL generateCodes();

Сначала я создал функцию, которая возвращает случайную строку из 6 символов, которые она использовала для генерации желаемых кодов:

DROP FUNCTION IF EXISTS getRandomAlphaNumeric;

DELIMITER $$

CREATE FUNCTION getRandomAlphaNumeric() RETURNS CHAR(6)
DETERMINISTIC
BEGIN

    SELECT 
    CONCAT (
        CHAR(FLOOR(RAND()*10)+48), CHAR(FLOOR(RAND()*26)+65), CHAR(FLOOR(RAND()*26)+97),
        CHAR(FLOOR(RAND()*10)+48), CHAR(FLOOR(RAND()*26)+65), CHAR(FLOOR(RAND()*26)+97)
    ) INTO @code
    ;

    RETURN @code;
END
$$

Затем я создал процедуру, которая отвечает за обновление таблицы со случайными уникальными кодами. Процедура состоит в следующем:

  • Подсчитайте все записи, которые будут обновлены свежим и случайным кодом из 6 символов.

    SELECT COUNT(1) INTO @count FROM demo.codes;

  • Затем строка foreach (используя цикл WHILE):

    • Получить идентификатор следующей записи, которая будет обновлена ​​

      PREPARE stmt FROM "SELECT @id := id, @itemCode := code FROM demo.codes p LIMIT ?, 1;"; EXECUTE stmt USING @i;

    • Получить новый код для записи:

      SET @code = getRandomAlphaNumeric();

    • Наконец, проверьте, не существует ли нового кода в таблице, и если в настоящий момент столбец поля не имеет значения (is NULL), если это не так, обновите текущий запись со случайным кодом:

      SELECT COUNT(1) INTO @countRowsWithCode FROM demo.codes WHERE code = @code; IF @countRowsWithCode = 0 AND @itemCode IS NULL THEN UPDATE demo.codes SET code = @code WHERE id = @id; END IF;

    • Наконец, CALL созданный PROCEDURE, чтобы заполнить поля из столбца code, которые NULL.

      CALL generateCodes();

Ответ 3

CONV(CONV(( SELECT MAX(CODE) FROM tbl ), 36, 10) + 1, 10, 36)

вы получите следующий "номер", закодированный в базе-36 (цифры и заглавные буквы).

Например:

SELECT CONV(CONV(( 'A1B2C' ), 36, 10) + 1, 10, 36); --> 'A1B2D'

Ответ 4

Попробуйте это для кода

SELECT LEFT(MD5(NOW()), 6) AS CODE;

LEFT(MD5(NOW()), 6) будет возвращен уникальный код с 6 символами.

Попробуйте другой способ:

SELECT LEFT(UUID(), 6);

LEFT(UUID(), 6) Это также возвращает уникальный код