복붙노트

[SQL] MySQL을 사용 임의 & 유일한 8 문자열을 생성

SQL

MySQL을 사용 임의 & 유일한 8 문자열을 생성

나는 어떤 시점에서 차량을 포함하는 게임에 일하고 있어요. 나는 어떤 상점 차량의 번호판을 열 "판"을 포함하여 차량에 대한 데이터를 포함하는 "자동차"라는 이름의 MySQL의 테이블이 있습니다.

이제 나는 여기에 문제가있어 일부 온다. 나는 새로운 차량을 만들기 전에 사용하지 않는 번호판을 찾아야 -이 영숫자 8 문자 임의의 문자열이어야합니다. 내가 달성하는 방법이 문자열을 생성하고 사용하는 경우 쿼리 DB보고, 나는에 프로그래밍하고있어 언어입니다 루아에서 잠시 루프를 사용했다. 그러나 차량의 수가 증가함에 따라,이 그것이 바로 지금 훨씬 더 비효율적이 될 것으로 기대합니다. 따라서, 나는 시도하고 MySQL의 쿼리를 사용하여이 문제를 해결하기로 결정했다.

쿼리 I 필요는 단순히 테이블에없는 8 영숫자 문자열을 생성한다. 나는 다시 생성 및 체크 루프 방식의 생각,하지만 난 단지의 경우에 그에게이 질문을 제한하지하고있어보다 효율적인 일이있다. 나는 아무것도 더 허용 된 모든 문자를 포함하는 문자열을 정의하고 무작위로 그것을 substringing,에 의해 문자열을 생성 할 수있었습니다.

어떤 도움에 감사드립니다.

해결법

  1. ==============================

    1.이 문제는 매우 다른 두 가지 하위 문제로 구성

    이 문제는 매우 다른 두 가지 하위 문제로 구성

    임의성이 아주 쉽게 달성되는 동안, 재시도 루프가없는 고유성이 없습니다. 이 먼저 고유성에 집중하는 우리를 제공합니다. 비 무작위 고유성은 하찮게 AUTO_INCREMENT로 달성 될 수있다. 괜찮을 것 고유성 보존, 의사 난수 변환을 사용 그래서 :

    같은 종자에 의해 생성 된 임의의 숫자의 순서로 보장됩니다

    우리는하지만 시드 RAND와, AndreyVolk의 @ 또는 GordonLinoff의 접근 @ 사용 그래서 :

    예를 들면 ID를 Assumin은 AUTO_INCREMENT 컬럼입니다 :

    INSERT INTO vehicles VALUES (blah); -- leaving out the number plate
    SELECT @lid:=LAST_INSERT_ID();
    UPDATE vehicles SET numberplate=concat(
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@lid)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed:=round(rand(@seed)*4294967296))*36+1, 1),
      substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand(@seed)*36+1, 1)
    )
    WHERE id=@lid;
    
  2. ==============================

    2.내 의견에 명시된 바와 같이 나는 충돌의 가능성 귀찮게 woudn't. 그냥 임의의 문자열을 생성하고이 존재하는지 확인. 만약 그렇다면, 다시 시도하면 더 그렇게 할 필요가 없습니다 당신이 이미 할당 된 판의 거대한 숫자가 없다면 몇 번.

    내 의견에 명시된 바와 같이 나는 충돌의 가능성 귀찮게 woudn't. 그냥 임의의 문자열을 생성하고이 존재하는지 확인. 만약 그렇다면, 다시 시도하면 더 그렇게 할 필요가 없습니다 당신이 이미 할당 된 판의 거대한 숫자가 없다면 몇 번.

    순수에 8 자 긴 의사 임의의 문자열을 생성하기위한 또 다른 해결책 (내) SQL :

    SELECT LEFT(UUID(), 8);
    

    다음 (의사 코드)를 시도 할 수 있습니다 :

    DO 
        SELECT LEFT(UUID(), 8) INTO @plate;
        INSERT INTO plates (@plate);
    WHILE there_is_a_unique_constraint_violation
    -- @plate is your newly assigned plate number
    

    이 게시물이 관심의 예상치 못한 수준을받은 이후로, 내가 ADTC의 의견을 강조하자 : 위의 코드 조각은 아주 바보이고 순차적 인 숫자를 생성합니다.

    대신이 같은 약간 덜 바보 임의성 시도 뭔가의 경우 :

    SELECT LEFT(MD5(RAND()), 8)
    

    그리고 사실 (cryptograpically 보안) 난수를 사용 RANDOM_BYTES 위해 () 대신 RAND보다 () (그러나 나는 응용 프로그램 계층에이 논리를 이동하는 것을 고려 것이다).

  3. ==============================

    3.무엇 후 처음 8 개 문자를 고려하여 MD5 (또는 다른) 순차적 인 정수의 해시를 계산하는 방법에 대한.

    무엇 후 처음 8 개 문자를 고려하여 MD5 (또는 다른) 순차적 인 정수의 해시를 계산하는 방법에 대한.

    MD5(1) = c4ca4238a0b923820dcc509a6f75849b => c4ca4238
    MD5(2) = c81e728d9d4c2f636f067f89cc14862c => c81e728d
    MD5(3) = eccbc87e4b5ce2fe28308fd9f2a7baf3 => eccbc87e
    

    기타

    주의 : 당신이 충돌하기 전에 할당 할 수 있습니다 얼마나 많은 생각이 없다 (그러나 그것은 알려진 상수 값이 될 것이다).

    편집 :이 지금 오래된 대답이지만, 내가 관찰에서, 그래서 내 손에 시간을 다시 보았다 ...

    모든 숫자의 확률 = 2.35 %

    모든 문자 확률 = 0.05 %

    제 1 충돌시 MD5 (82,945) = "7b763dcb"(MD5와 같은 결과 (25,302))

  4. ==============================

    4.임의의 문자열을 만들기

    임의의 문자열을 만들기

    여기에 주어진 길이의 임의의 문자열을 만들 수있는 MySQL의 기능입니다.

    DELIMITER $$
    
    CREATE DEFINER=`root`@`%` FUNCTION `RandString`(length SMALLINT(3)) RETURNS varchar(100) CHARSET utf8
    begin
        SET @returnStr = '';
        SET @allowedChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        SET @i = 0;
    
        WHILE (@i < length) DO
            SET @returnStr = CONCAT(@returnStr, substring(@allowedChars, FLOOR(RAND() * LENGTH(@allowedChars) + 1), 1));
            SET @i = @i + 1;
        END WHILE;
    
        RETURN @returnStr;
    END
    

    사용 SELECT RANDSTRING (8) 8 문자열을 반환합니다.

    당신은 @allowedChars을 사용자 정의 할 수 있습니다.

    고유성이 보장되지 않습니다 - 당신은 다른 솔루션에 대한 코멘트에서 살펴 보 겠지만, 이것은 단지 수 없습니다. 대신에 당신은 문자열을 생성 이미 사용 있는지 확인하고 있는지 다시 시도해야합니다.

    임의의 문자열이 이미 사용중인 경우 확인

    우리는 응용 프로그램에서 코드를 검사 충돌을 유지하려면, 우리는 트리거를 만들 수 있습니다 :

    DELIMITER $$
    
    CREATE TRIGGER Vehicle_beforeInsert
      BEFORE INSERT ON `Vehicle`
      FOR EACH ROW
      BEGIN
        SET @vehicleId = 1;
        WHILE (@vehicleId IS NOT NULL) DO 
          SET NEW.plate = RANDSTRING(8);
          SET @vehicleId = (SELECT id FROM `Vehicle` WHERE `plate` = NEW.plate);
        END WHILE;
      END;$$
    DELIMITER ;
    
  5. ==============================

    5.다음은 유효한 문자로 영숫자를 사용하여 하나의 방법입니다 :

    다음은 유효한 문자로 영숫자를 사용하여 하나의 방법입니다 :

    select concat(substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1),
                  substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', rand()*36+1, 1)
                 ) as LicensePlaceNumber;
    

    유일성 보장은 없습니다 있습니다. 당신은 따로 확인해야합니다.

  6. ==============================

    6.여기에 임의의 문자열을 생성하는 또 다른 방법입니다 :

    여기에 임의의 문자열을 생성하는 또 다른 방법입니다 :

    SELECT SUBSTRING (MD5 (RAND ()) 1 내지 8) myrandomstring AS

  7. ==============================

    7.당신은 MySQL을의 랜드 ()와 문자 () 함수를 사용할 수 있습니다 :

    당신은 MySQL을의 랜드 ()와 문자 () 함수를 사용할 수 있습니다 :

    select concat( 
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97),
        char(round(rand()*25)+97)
    ) as name;
    
  8. ==============================

    8.당신과 함께 임의의 영숫자 문자열을 생성 할 수 있습니다 :

    당신과 함께 임의의 영숫자 문자열을 생성 할 수 있습니다 :

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

    당신은 BEFORE INSERT 트리거에서 사용하고있는 동안 루프에 중복을 확인할 수 있습니다 :

    CREATE TABLE `vehicles` (
        `plate` CHAR(8) NULL DEFAULT NULL,
        `data` VARCHAR(50) NOT NULL,
        UNIQUE INDEX `plate` (`plate`)
    );
    
    DELIMITER //
    CREATE TRIGGER `vehicles_before_insert` BEFORE INSERT ON `vehicles`
    FOR EACH ROW BEGIN
    
        declare str_len int default 8;
        declare ready int default 0;
        declare rnd_str text;
        while not ready do
            set rnd_str := lpad(conv(floor(rand()*pow(36,str_len)), 10, 36), str_len, 0);
            if not exists (select * from vehicles where plate = rnd_str) then
                set new.plate = rnd_str;
                set ready := 1;
            end if;
        end while;
    
    END//
    DELIMITER ;
    

    지금은 단지처럼 데이터를 삽입

    insert into vehicles(col1, col2) values ('value1', 'value2');
    

    트리거 플레이트 컬럼에 대한 값을 생성한다.

    (sql 휘티 d 혀라도)

    열이 널 (NULL)을 허용 할 경우 즉,이 방식으로 작동합니다. 당신이 NOT NULL 싶은 경우에 당신은 기본 값을 정의해야합니다

    `plate` CHAR(8) NOT NULL DEFAULT 'default',
    

    대문자 알파벳과 숫자가 당신이 원하는하지 않은 경우 당신은 또한 트리거에 다른 임의의 문자열 생성 알고리즘을 사용할 수 있습니다. 그러나 트리거는 고유성 처리됩니다.

  9. ==============================

    9.임의의 문자열을 생성하는 경우, 당신은 사용할 수 있습니다 :

    임의의 문자열을 생성하는 경우, 당신은 사용할 수 있습니다 :

    문자열 (MD5 (RAND ()) 1 ~ 8)

    당신은 그런 식으로 떨어지게가 나타납니다

    353 개 AKH 0 사스

  10. ==============================

    10.알파벳 8 개 문자 - 모든 캡 :

    알파벳 8 개 문자 - 모든 캡 :

    UPDATE `tablename` SET `tablename`.`randomstring`= concat(CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25)))CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))),CHAR(FLOOR(65 + (RAND() * 25))));
    
  11. ==============================

    11.8 개 임의의 숫자와 대문자와 소문자로 구성된 문자열의 경우,이 내 솔루션입니다 :

    8 개 임의의 숫자와 대문자와 소문자로 구성된 문자열의 경우,이 내 솔루션입니다 :

    LPAD(LEFT(REPLACE(REPLACE(REPLACE(TO_BASE64(UNHEX(MD5(RAND()))), "/", ""), "+", ""), "=", ""), 8), 8, 0)
    

    안에서부터 밖으로 설명 :

  12. ==============================

    12.다른 열에서 I를 사용하여 데이터는 "해시"또는 고유 한 문자열을 생성하는

    다른 열에서 I를 사용하여 데이터는 "해시"또는 고유 한 문자열을 생성하는

    UPDATE table_name SET column_name = Right( MD5(another_column_with_data), 8 )
    
  13. ==============================

    13.당신은 ID 또는 종자가없는 경우는 그 삽입의 값 목록과 같은 :

    당신은 ID 또는 종자가없는 경우는 그 삽입의 값 목록과 같은 :

    REPLACE(RAND(), '.', '')
    
  14. ==============================

    14."임의"하지만 완전히 예측 번호판 나왔습니다 확인 당신이 경우, 당신은 다음 판 번호를 선택하기 위해 선형 피드백 시프트 레지스터를 사용할 수 있습니다 - 반복하기 전에 모든 전화 번호를 통해 이동을 보장합니다. 그러나 일부 복잡한 수학없이, 당신은 모든 8 문자 영숫자 문자열을 통과 할 수 없습니다 (당신은) 36 ^ 8 (78 %에서 가능 판을 ^ (41) 2를 얻을 수 있습니다). 당신의 공간 나은이 채우기를하려면, 당신은 당신에게 97 %를주는 판 (아마도 O) 편지를 제외 할 수 있습니다.

    "임의"하지만 완전히 예측 번호판 나왔습니다 확인 당신이 경우, 당신은 다음 판 번호를 선택하기 위해 선형 피드백 시프트 레지스터를 사용할 수 있습니다 - 반복하기 전에 모든 전화 번호를 통해 이동을 보장합니다. 그러나 일부 복잡한 수학없이, 당신은 모든 8 문자 영숫자 문자열을 통과 할 수 없습니다 (당신은) 36 ^ 8 (78 %에서 가능 판을 ^ (41) 2를 얻을 수 있습니다). 당신의 공간 나은이 채우기를하려면, 당신은 당신에게 97 %를주는 판 (아마도 O) 편지를 제외 할 수 있습니다.

  15. ==============================

    15.계정에 당신이 필요로하는 문자의 수를 가지고 가서, 당신은이 정확히 유사한 번호판을 생성하는 아주 작은 기회를 가질 것입니다. 따라서 당신은 아마 LUA의 숫자를 생성 멀리 얻을 수 있습니다.

    계정에 당신이 필요로하는 문자의 수를 가지고 가서, 당신은이 정확히 유사한 번호판을 생성하는 아주 작은 기회를 가질 것입니다. 따라서 당신은 아마 LUA의 숫자를 생성 멀리 얻을 수 있습니다.

    당신은 36 ^ 8 개의 다른 독특한 numberplates을 (2,821,109,907,456, 즉 많은입니다), 이미 만 numberplates 이미했다하더라도, 당신은 0.000035 %에 대해 당신이 이미 가지고있는 하나를 생성하는 아주 작은 기회를 가질 것 가지고

    물론, 그것은 모두 당신이 만드는 결국 얼마나 많은 numberplates에 따라 달라집니다.

  16. ==============================

    16.이 기능은 입력 길이에 따라이 같은 문자를 허용 무작위 문자열을 생성합니다 :

    이 기능은 입력 길이에 따라이 같은 문자를 허용 무작위 문자열을 생성합니다 :

    SELECT str_rand(8, '23456789abcdefghijkmnpqrstuvwxyz');
    

    기능 코드 :

    DROP FUNCTION IF EXISTS str_rand;
    
    DELIMITER //
    
    CREATE FUNCTION str_rand(
        u_count INT UNSIGNED,
        v_chars TEXT
    )
    RETURNS TEXT
    NOT DETERMINISTIC
    NO SQL
    SQL SECURITY INVOKER
    COMMENT ''
    BEGIN
        DECLARE v_retval TEXT DEFAULT '';
        DECLARE u_pos    INT UNSIGNED;
        DECLARE u        INT UNSIGNED;
    
        SET u = LENGTH(v_chars);
        WHILE u_count > 0
        DO
          SET u_pos = 1 + FLOOR(RAND() * u);
          SET v_retval = CONCAT(v_retval, MID(v_chars, u_pos, 1));
          SET u_count = u_count - 1;
        END WHILE;
    
        RETURN v_retval;
    END;
    //
    DELIMITER ;
    

    이 코드는 셔플 문자열 함수에 근거은 "로스 스미스 II"에 의해 전송

  17. ==============================

    17.

    DELIMITER $$
    
    USE `temp` $$
    
    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')
    
  18. ==============================

    18.고유 번호를 생성하는 쉬운 방법

    고유 번호를 생성하는 쉬운 방법

    set @i = 0;
    update vehicles set plate = CONCAT(@i:=@i+1, ROUND(RAND() * 1000)) 
    order by rand();
    
  19. ==============================

    19.8 자 키를 생성

    8 자 키를 생성

    lpad(conv(floor(rand()*pow(36,6)), 10, 36), 8, 0); 
    
  20. ==============================

    20.나는 비슷한 뭔가를 찾고 있었고, 난 매개 변수로 원한다면 당신은 또한 다른 씨앗을 지정할 수 있습니다 내 자신의 버전 (문자 목록)을 만들기로 결정했다 :

    나는 비슷한 뭔가를 찾고 있었고, 난 매개 변수로 원한다면 당신은 또한 다른 씨앗을 지정할 수 있습니다 내 자신의 버전 (문자 목록)을 만들기로 결정했다 :

    CREATE FUNCTION `random_string`(length SMALLINT(3), seed VARCHAR(255)) RETURNS varchar(255) CHARSET utf8
        NO SQL
    BEGIN
        SET @output = '';
    
        IF seed IS NULL OR seed = '' THEN SET seed = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; END IF;
    
        SET @rnd_multiplier = LENGTH(seed);
    
        WHILE LENGTH(@output) < length DO
            # Select random character and add to output
            SET @output = CONCAT(@output, SUBSTRING(seed, RAND() * (@rnd_multiplier + 1), 1));
        END WHILE;
    
        RETURN @output;
    END
    

    으로 사용할 수 있습니다 :

    SELECT random_string(10, '')
    

    어떤는 대문자의 씨앗에 내장 소문자 문자 + 숫자를 사용합니다. NULL은 대신 ''의 값이 될 것입니다.

    호출하는 동안 그러나 하나는 정의의 씨앗을 지정할 수 있습니다 :

    SELECT random_string(10, '1234')
    
  21. ==============================

    21.닮은 문자의 01oOlI을 제외한 임의의 10 자리 숫자를 만들려면 :

    닮은 문자의 01oOlI을 제외한 임의의 10 자리 숫자를 만들려면 :

    LPAD(LEFT(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TO_BASE64(UNHEX(MD5(RAND()))), "/", ""), "+", ""), "=", ""), "O", ""), "l", ""), "I", ""), "1", ""), "0", ""), "o", ""), 10), 10, 0)
    

    이것은 내가 쿠폰 코드를 작성하는 데 필요한 정확히입니다. 혼동 문자는 쿠폰 코드의 양식에 입력 할 때 오류를 줄이기 위해 제거됩니다.

    이 월 Uhlig의 훌륭한 답변에 따라, 누군가를하는 데 도움이 희망.

    이 코드가 어떻게 작동하는지에 대한 분석을 위해 월의 답변을 참조하시기 바랍니다.

  22. ==============================

    22.간단하고 효율적인 솔루션은 대문자와 소문자와 숫자로 임의의 10 자 문자열을 얻을 수 있습니다 :

    간단하고 효율적인 솔루션은 대문자와 소문자와 숫자로 임의의 10 자 문자열을 얻을 수 있습니다 :

    select substring(base64_encode(md5(rand())) from 1+rand()*4 for 10);
    
  23. from https://stackoverflow.com/questions/16737910/generating-a-random-unique-8-character-string-using-mysql by cc-by-sa and MIT license