Tạo chuỗi 8 ký tự ngẫu nhiên và duy nhất bằng MySQL


110

Tôi đang làm một trò chơi liên quan đến xe cộ tại một số điểm. Tôi có một bảng MySQL tên là "các phương tiện" chứa dữ liệu về các phương tiện, bao gồm cả cột "tấm" lưu trữ các Biển số cho phương tiện.

Bây giờ đến phần tôi đang gặp vấn đề. Tôi cần tìm một biển số chưa sử dụng trước khi tạo một chiếc xe mới - nó phải là một chuỗi ký tự ngẫu nhiên gồm 8 ký tự gồm chữ và số. Cách tôi đạt được điều này là sử dụng vòng lặp while trong Lua, là ngôn ngữ tôi đang lập trình, để tạo chuỗi và truy vấn DB để xem nó có được sử dụng hay không. Tuy nhiên, khi số lượng phương tiện tăng lên, tôi cho rằng điều này sẽ trở nên kém hiệu quả hơn nữa. Do đó, tôi quyết định thử và giải quyết vấn đề này bằng cách sử dụng truy vấn MySQL.

Truy vấn tôi cần chỉ cần tạo ra một chuỗi gồm 8 ký tự chữ và số chưa có trong bảng. Tôi đã nghĩ đến cách tiếp cận vòng lặp tạo & kiểm tra một lần nữa, nhưng tôi không giới hạn câu hỏi này chỉ trong trường hợp có một cách hiệu quả hơn. Tôi đã có thể tạo chuỗi bằng cách xác định một chuỗi chứa tất cả các ký tự được phép và xâu chuỗi con một cách ngẫu nhiên, và không có gì khác.

Bất kỳ trợ giúp được đánh giá cao.


Bạn cần những thứ này ngẫu nhiên như thế nào? Nếu ai đó nhận được một biển số cụ thể, điều quan trọng là họ có thể tìm ra biển số tiếp theo hoặc trước đó mà bạn đã trao hay không?
Damien_The_Un Believer

@YaK Xem câu trả lời của tôi về cách tránh ngay cả khả năng va chạm rất nhỏ
Eugen Rieck

Câu trả lời:


87

Vấn đề này bao gồm hai vấn đề phụ rất khác nhau:

  • chuỗi phải có vẻ ngẫu nhiên
  • chuỗi phải là duy nhất

Mặc dù tính ngẫu nhiên khá dễ dàng đạt được, nhưng tính duy nhất không có vòng lặp thử lại thì không. Điều này khiến chúng tôi tập trung vào tính độc đáo trước tiên. Tính duy nhất không ngẫu nhiên có thể đạt được với AUTO_INCREMENT. Vì vậy, sử dụng một phép biến đổi giả ngẫu nhiên, bảo toàn tính duy nhất sẽ ổn:

  • Hàm băm đã được đề xuất bởi @paul
  • Mã hóa AES cũng phù hợp
  • Nhưng có một cái hay: RAND(N)chính nó!

Một chuỗi các số ngẫu nhiên được tạo bởi cùng một hạt giống được đảm bảo là

  • có thể tái sản xuất
  • khác nhau trong 8 lần lặp đầu tiên
  • nếu hạt giống là một INT32

Vì vậy, chúng tôi sử dụng phương pháp tiếp cận của @ AndreyVolk hoặc @ GordonLinoff, nhưng với một hạt giống RAND :

ví dụ: Assumin idlà một AUTO_INCREMENTcột:

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;

Phương pháp tiếp cận rất giao nhau, nhưng bạn có thể có ý RAND(LAST_INSERT_ID()); UPDATE vehicles (...) , rand()*36+1, (...)(hoặc nếu không thì nó trả về 8 lần cùng một ký tự). Làm thế nào chúng ta có thể chắc chắn rằng 8 lệnh gọi liên tiếp rand()được đảm bảo trả về một chuỗi khác nếu được khởi tạo bằng một hạt khác?
RandomSeed

8
Tôi chỉ đang tự hỏi. Tại sao bạn lại sử dụng những con số đó ..4294967296)) * 36 + 1?
Mick

7
Điều này hơi cũ nhưng tôi muốn lưu ý rằng tôi đã phải thêm FLOOR()xung quanh các tham số chuỗi con thứ hai: substring('ABC … 789', floor(rand(@seed:= … )*36+1), 1), Trong một số trường hợp, chuỗi con đang cố gắng chọn ký tự 36,9, khi làm tròn thành 37, sẽ không có ký tự nào được chọn.
Phillip Dodson

4
Bạn không thể gọi một chuỗi là ngẫu nhiên nếu nó có thể tái tạo. Và các bản sao cũng có thể xảy ra, bởi vì bạn đang sử dụng floor(). Sqlfiddle này cho thấy rằng các bản sao được tạo cho chuỗi dài ba ký tự.
Paul Spiegel

6
@EugenRieck Tôi không hiểu cách bạn lấy số của mình ("2 ^ 32 lần lặp đầu tiên"). Nhưng tôi chỉ cần một ví dụ về các bản sao để bác bỏ khái niệm này. Đối với các ID 193844775771thuật toán của bạn sẽ tạo ra cùng một chuỗi T82X711( demo ).
Paul Spiegel

113

Như tôi đã nêu trong nhận xét của mình, tôi sẽ không bận tâm đến khả năng va chạm. Chỉ cần tạo một chuỗi ngẫu nhiên và kiểm tra xem nó có tồn tại hay không. Nếu có, hãy thử lại và bạn không cần phải làm điều đó nhiều hơn một vài lần trừ khi bạn đã chỉ định một số lượng lớn các tấm.

Một giải pháp khác để tạo chuỗi giả ngẫu nhiên dài 8 ký tự trong SQL thuần túy (của tôi):

SELECT LEFT(UUID(), 8);

Bạn có thể thử những cách sau (mã giả):

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

Vì bài đăng này đã nhận được một mức độ chú ý bất ngờ, hãy để tôi làm nổi bật nhận xét của ADTC : đoạn mã ở trên khá ngớ ngẩn và tạo ra các chữ số liên tiếp.

Đối với sự ngẫu nhiên ít ngu ngốc hơn một chút, hãy thử một cái gì đó như sau:

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

Và đối với sự ngẫu nhiên thực sự (an toàn về mặt mật mã), hãy sử dụng RANDOM_BYTES()thay vì RAND()(nhưng sau đó tôi sẽ xem xét chuyển logic này lên lớp ứng dụng).


Cảm ơn giải pháp của bạn, tôi có một câu hỏi liên quan đến UUID. Có bao nhiêu khả năng id bạn tạo 8 ký tự lặp lại.
TR-Ahmed

1
@ user3099183 Chính thức là "rất thấp". 16 ^ 8 là khoảng 4 tỷ chuỗi có thể.
RandomSeed

23
Xin lưu ý rằng 8 ký tự đầu tiên của UUID không phải là ngẫu nhiên, mà là tuần tự, vì nó dựa trên dấu thời gian.
ADTC

Tôi muốn tạo một chuỗi ngẫu nhiên dài 9 ký tự và khi tôi sử dụng 9trong mã của bạn SELECT LEFT(UUID(), 9);, luôn có -ở cuối chuỗi được tạo là ký tự thứ chín. Nó không đổi. Tại sao?
Martin AJ ngày

3
@MartinAJ vì chuỗi là một uuid . Bạn có thể dễ dàng thay thế các dấu gạch nối ví dụSELECT LEFT(REPLACE(UUID(), '-', ''), 16);
jchook

53

Còn việc tính toán băm MD5 (hoặc khác) của các số nguyên tuần tự, sau đó lấy 8 ký tự đầu tiên.

I E

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

Vân vân.

cảnh báo: Tôi không biết bạn có thể phân bổ bao nhiêu trước khi va chạm (nhưng nó sẽ là một giá trị đã biết và không đổi).

chỉnh sửa: Đây bây giờ là một câu trả lời cũ, nhưng tôi đã nhìn thấy nó một lần nữa với thời gian trên tay, vì vậy, từ quan sát ...

Cơ hội của tất cả các số = 2,35%

Cơ hội của tất cả các chữ cái = 0,05%

Va chạm đầu tiên khi MD5 (82945) = "7b763dcb ..." (cùng kết quả với MD5 (25302))


2
Ý tưởng hay, có thể sử dụng nó trên khóa chính. Sẽ ghi nhớ điều này cho các dự án trong tương lai, cảm ơn!
funstein

2
Có một cơ hội mà điều này có thể gây ra với số lượng chỉ
Mladen Janjetovic

9
Nó không phải là ngẫu nhiên chút nào.
paul

1
Bạn có thể làm cho nó "ngẫu nhiên" hơn nếu thay vì sử dụng id tăng dần tự động, bạn sử dụng ngày giờ thực hiện việc chèn, cũng là duy nhất.
Javier La Banca

35

Tạo một chuỗi ngẫu nhiên

Đây là một hàm MySQL để tạo một chuỗi ngẫu nhiên có độ dài nhất định.

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

Sử dụng SELECT RANDSTRING(8)để trả về một chuỗi 8 ký tự.

Bạn có thể tùy chỉnh @allowedChars.

Tính duy nhất không được đảm bảo - như bạn sẽ thấy trong các nhận xét cho các giải pháp khác, điều này là không thể. Thay vào đó, bạn sẽ cần tạo một chuỗi, kiểm tra xem nó đã được sử dụng chưa và thử lại nếu có.


Kiểm tra xem chuỗi ngẫu nhiên đã được sử dụng chưa

Nếu chúng tôi muốn giữ mã kiểm tra xung đột khỏi ứng dụng, chúng tôi có thể tạo trình kích hoạt:

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 ;

6
đây sẽ là câu trả lời được chấp nhận, rõ ràng và vào vấn đề, chỉ làm việc tốt cho tôi, cảm ơn @ lúa-mann
Saif

Đây là giải pháp tốt nhất mà tôi nghĩ. Cảm ơn anh bạn!
Pronoy999

23

Đây là một cách, sử dụng số alpha làm ký tự hợp lệ:

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;

Lưu ý không có đảm bảo về tính duy nhất. Bạn sẽ phải kiểm tra điều đó một cách riêng biệt.


7
thay vào đó hãy sử dụng tầng (rand () * 36 + 1). Nếu không, một số kết quả sẽ 'ngắn'.
Fraggle

2
không nên có 35 + 1 chứ không phải 36 + 1! Nếu không, bạn sẽ nhận được một số một số chuỗi với 8 ký tự và một số trong số họ với 7
NGUY CƠ SINH HỌC

23

Đây là một phương pháp khác để tạo một chuỗi ngẫu nhiên:

SELECT SUBSTRING(MD5(RAND()) FROM 1 FOR 8) AS myrandomstring


16

Bạn có thể sử dụng hàm rand ()char () của 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;

14

Bạn có thể tạo một chuỗi chữ và số ngẫu nhiên với:

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

Bạn có thể sử dụng nó trong trình BEFORE INSERTkích hoạt và kiểm tra bản sao trong vòng lặp while:

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 ;

Bây giờ chỉ cần chèn dữ liệu của bạn như

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

Và trình kích hoạt sẽ tạo ra một giá trị cho platecột.

( sqlfiddle demo )

Điều đó hoạt động theo cách này nếu cột cho phép NULL. Nếu bạn muốn nó KHÔNG ĐỦ, bạn sẽ cần xác định một giá trị mặc định

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

Bạn cũng có thể sử dụng bất kỳ thuật toán tạo chuỗi ngẫu nhiên nào khác trong trình kích hoạt nếu chữ và số viết hoa không phải là những gì bạn muốn. Nhưng trình kích hoạt sẽ quan tâm đến tính duy nhất.


Kinh ngạc! Đây chính xác là những gì tôi muốn. Tôi chỉ muốn hiểu cách nó được chuyển đổi thành một chuỗi. Tại sao có một pow, phải làm gì, để thêm số và vân vân. Dù sao, cảm ơn bạn.
Akxe

@Akxe convert () có thể được sử dụng để chuyển đổi một số thành một chuỗi chữ và số. pow(36,8)-1là đại diện số của ZZZZZZZZ. Vì vậy, chúng tôi tạo một số nguyên ngẫu nhiên giữa 0và '36 ^ 8-1 '(từ 0đến 2821109907455) và chuyển đổi nó thành một chuỗi chữ và số giữa 0ZZZZZZZZunsing conv(). Lapad () sẽ điền vào chuỗi với số không cho đến khi nó có chiều dài 8.
Paul Spiegel

Ngài là một thiên tài. Tôi tưởng tượng việc thêm các chữ cái nhỏ là không thể do tính không liên tục của các ký tự? (91-96) Không phải tôi cần, chỉ là tò mò ...
Akxe

@Akxe conv()chỉ hỗ trợ tối đa 36 (10 chữ số + 26 chữ hoa). Nếu bạn muốn bao gồm các chữ cái viết thường, bạn sẽ cần một cách khác để chuyển một số thành một chuỗi.
Paul Spiegel

Lưu ý: không hoạt động đối với str_len> 13. Từ ngày 14 trở đi, bạn luôn nhận được '3W5E11264SGSF'. ;-)
Gerard H. Pille

6

Để tạo chuỗi ngẫu nhiên, bạn có thể sử dụng:

SUBSTRING(MD5(RAND()) FROM 1 FOR 8)

Bạn nhận được smth như thế:

353E50CC


5

Đối với một Chuỗi bao gồm 8 số ngẫu nhiên và các chữ cái viết hoa và viết thường, đây là giải pháp của tôi:

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

Giải thích từ trong ra ngoài:

  1. RAND tạo một số ngẫu nhiên từ 0 đến 1
  2. MD5 tính tổng MD5 của (1), 32 ký tự từ af và 0-9
  3. UNHEX dịch (2) thành 16 byte có giá trị từ 00 đến FF
  4. TO_BASE64 mã hóa (3) dưới dạng base64, 22 ký tự từ az và AZ và 0-9 cộng với "/" và "+", theo sau là hai "="
  5. ba REPLACEký tự xóa các ký tự "/", "+" và "=" khỏi (4)
  6. LEFT lấy 8 ký tự đầu tiên từ (5), thay đổi 8 thành ký tự khác nếu bạn cần nhiều hoặc ít ký tự hơn trong chuỗi ngẫu nhiên của mình
  7. LPADchèn các số 0 vào đầu (6) nếu nó dài dưới 8 ký tự; một lần nữa, thay đổi 8 thành một cái gì đó khác nếu cần

Tuyệt vời, chính xác những gì tôi đang tìm kiếm để tạo một ID giống như mã thông báo nguyên bản trong MySQL
rabudde vào

4

Tôi Sử dụng dữ liệu từ một cột khác để tạo "băm" hoặc chuỗi duy nhất

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

4

8 chữ cái trong bảng chữ cái - Viết hoa tất cả:

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))));

3

Nếu bạn không có id hoặc hạt giống, hãy giống như nó cho danh sách giá trị trong chèn:

REPLACE(RAND(), '.', '')

2

Giải pháp đơn giản và hiệu quả để lấy một chuỗi 10 ký tự ngẫu nhiên với các chữ cái viết hoa, viết thường và các chữ số:

select substring(base64_encode(md5(rand())) from 1+rand()*4 for 10);

1

Nếu bạn đồng ý với biển số xe "ngẫu nhiên" nhưng hoàn toàn có thể dự đoán được, bạn có thể sử dụng thanh ghi dịch chuyển phản hồi tuyến tính để chọn biển số tiếp theo - nó đảm bảo đi qua mọi số trước khi lặp lại. Tuy nhiên, nếu không có một số phép toán phức tạp, bạn sẽ không thể đọc hết mỗi chuỗi chữ và số 8 ký tự (bạn sẽ nhận được 2 ^ 41 trong số 36 ^ 8 (78%) tấm có thể có). Để làm cho điều này lấp đầy không gian của bạn tốt hơn, bạn có thể loại trừ một chữ cái khỏi các tấm (có thể là O), cho bạn 97%.


1

Tính đến tổng số ký tự mà bạn yêu cầu, bạn sẽ có cơ hội rất nhỏ để tạo ra hai biển số giống hệt nhau. Vì vậy, bạn có thể thoát khỏi việc tạo các số trong LUA.

Bạn có 36 ^ 8 bảng số duy nhất khác nhau (2,821,109,907,456, đó là rất nhiều), ngay cả khi bạn đã có một triệu bảng số, bạn sẽ có cơ hội rất nhỏ để tạo ra một bảng số bạn đã có, khoảng 0,000035%

Tất nhiên, tất cả phụ thuộc vào việc bạn sẽ tạo bao nhiêu bảng số.


Đúng, tôi sẽ tiếp tục làm điều đó trong trò chơi thực tế thay vì SQL. Cảm ơn rât nhiều.
funstein

1

Hàm này tạo một chuỗi Ngẫu nhiên dựa trên độ dài đầu vào của bạn và các ký tự được phép như sau:

SELECT str_rand(8, '23456789abcdefghijkmnpqrstuvwxyz');

mã chức năng:

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 ;

Mã này dựa trên hàm chuỗi xáo trộn do "Ross Smith II" gửi


Hàm này sẽ không tạo ra giá trị duy nhất ngẫu nhiên.
Faisal

1

Để tạo một chữ và số ngẫu nhiên gồm 10 chữ số , không bao gồm các ký tự lookalike 01oOlI:

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)

Đây chính là thứ tôi cần để tạo mã phiếu thưởng . Các ký tự khó hiểu được loại bỏ để giảm lỗi khi nhập vào mẫu mã chứng từ.

Hy vọng điều này sẽ giúp ai đó, dựa trên câu trả lời tuyệt vời của Jan Uhlig .

Vui lòng xem câu trả lời của Jan để biết phân tích về cách mã này hoạt động.


0
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 ;

Sử dụng quy trình được lưu trữ này và sử dụng nó mọi lúc như

Call GenerateUniqueValue('tableName','columnName')

0

Một cách dễ dàng để tạo một số duy nhất

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


0

Tôi đang tìm kiếm thứ gì đó tương tự và tôi quyết định tạo phiên bản của riêng mình, nơi bạn cũng có thể chỉ định một hạt giống khác nếu muốn (danh sách các ký tự) làm tham số:

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

Có thể được sử dụng như:

SELECT random_string(10, '')

Điều này sẽ sử dụng hạt giống tích hợp của các ký tự viết hoa và viết thường + chữ số. NULL cũng sẽ là giá trị thay vì ''.

Nhưng người ta có thể chỉ định một hạt giống tùy chỉnh trong khi gọi:

SELECT random_string(10, '1234')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.