it-roy-ru.com

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

Я использую 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 потому что эта ссылка имеет дело с идентификаторами, которые являются числовыми. Мои идентификаторы представляют собой 32-символьные строки. Кроме того, их решение не учитывает тот факт, что в таблице могут быть значения до запуска операторов, которые я хочу выполнить, которые будут генерировать уникальные значения для рассматриваемого столбца.

16
Dave

ДО ОБНОВЛЕНИЯ триггерного решения:

Вы можете создать 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

Так что насчет уникальности? Хорошо - попробуйте сгенерировать дубликаты ;-)

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

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

Например:

SELECT CONV(CONV(( 'A1B2C' ), 36, 10) + 1, 10, 36); --> 'A1B2D'
1
Rick James
DELIMITER $$

USE `db` $$

DROP PROCEDURE IF EXISTS `GenerateUniqueValue`$$

CREATE PROCEDURE `GenerateUniqueValue`(IN tableName VARCHAR(255),IN columnName VARCHAR(255)) 
BEGIN
    DECLARE uniqueValue VARCHAR(8) DEFAULT "";
    WHILE LENGTH(uniqueValue) = 0 DO
        SELECT CONCAT(SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1),
                SUBSTRING('ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789', Rand()*34+1, 1)
                ) INTO @newUniqueValue;
        SET @rcount = -1;
        SET @query=CONCAT('SELECT COUNT(*) INTO @rcount FROM  ',tableName,' WHERE ',columnName,'  like ''',@newUniqueValue,'''');
        PREPARE stmt FROM  @query;
        EXECUTE stmt;
        DEALLOCATE PREPARE stmt;
    IF @rcount = 0 THEN
            SET uniqueValue = @newUniqueValue ;
        END IF ;
    END WHILE ;
    SELECT uniqueValue;
    END$$

DELIMITER ;

Вызовите эту хранимую процедуру как 

Call GenerateUniqueValue('tableName','columnName')

Это даст вам уникальную 8-символьную строку каждый раз. 

0
Hariramprasath Nandhagopalan

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

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;

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

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

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

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

      SET @code = getRandomAlphaNumeric();

    • Наконец, проверьте, не существует ли новый код в таблице, и если в данный момент столбец поля не имеет значения (это 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();

0
Cristian Gonçalves

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

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

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

Попробуйте другой способ, как это 

SELECT LEFT(UUID(), 6);

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

0
krunal nerikar