MySQL kullanarak rastgele ve benzersiz bir 8 karakter dizisi oluşturma


111

Bir noktada araçları içeren bir oyun üzerinde çalışıyorum. Araçların Plakalarını saklayan "plaka" sütunu dahil olmak üzere, araçlar hakkındaki verileri içeren "araçlar" adlı bir MySQL tablom var.

Şimdi sorun yaşadığım kısım geliyor. Yeni bir araç oluşturmadan önce kullanılmamış bir plaka bulmam gerekiyor - bu bir alfanümerik 8 karakterli rastgele dizge olmalıdır. Bunu nasıl başardım, programlama yaptığım dil olan Lua'da dizeleri oluşturmak ve kullanılıp kullanılmadığını görmek için DB'yi sorgulamak için bir while döngüsü kullanmaktı. Ancak araç sayısı arttıkça bunun daha da verimsiz hale gelmesini bekliyorum, şu an için. Bu nedenle, bu sorunu bir MySQL sorgusu kullanarak denemeye ve çözmeye karar verdim.

İhtiyacım olan sorgu, zaten tabloda bulunmayan 8 karakterli bir alfasayısal dize oluşturmalıdır. Tekrar üret ve kontrol döngüsü yaklaşımını düşündüm, ancak bu soruyu sadece daha verimli bir yaklaşım olması durumunda bununla sınırlandırmıyorum. İzin verilen tüm karakterleri içeren ve rastgele alt dizeler içeren bir dizge tanımlayarak dizeler üretebildim ve daha fazlasını yapmadım.

Herhangi bir yardım takdir edilmektedir.


Bunların ne kadar rastgele olmasına ihtiyacınız var? Birisi belirli bir plaka alırsa, sizin verdiğiniz sonraki veya önceki plakayı hesaplayıp çıkaramayacağı önemli mi?
Damien_The_Unbeliever

@YaK En ufak bir çarpışma olasılığından nasıl kaçınılacağına dair cevabımı görün
Eugen Rieck

Yanıtlar:


87

Bu problem çok farklı iki alt problemden oluşmaktadır:

  • dizi görünüşte rastgele olmalı
  • dize benzersiz olmalıdır

Rastgelelik oldukça kolay bir şekilde elde edilirken, bir yeniden deneme döngüsü olmadan benzersizlik elde edilemez. Bu, önce benzersizliğe odaklanmamızı sağlar. Rastgele olmayan benzersizlik, önemsiz bir şekilde elde edilebilir AUTO_INCREMENT. Dolayısıyla, benzersizliği koruyan, sözde rastgele dönüşüm kullanmak iyi olur:

  • Hash @paul tarafından önerildi
  • AES şifreleme de uyar
  • Ama güzel bir tane var: RAND(N)kendisi!

Aynı tohum tarafından oluşturulan bir rastgele sayı dizisinin olması garanti edilir.

  • tekrarlanabilir
  • ilk 8 yineleme için farklı
  • eğer tohum bir INT32

Bu nedenle, @ AndreyVolk veya @ GordonLinoff'un yaklaşımını kullanıyoruz, ancak bir tohumla RAND :

örneğin, Assumin idbir AUTO_INCREMENTsütundur:

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;

Çok ilgi çekici bir yaklaşım, ancak muhtemelen kastettiniz RAND(LAST_INSERT_ID()); UPDATE vehicles (...) , rand()*36+1, (...)(ya da aynı karakterin 8 katını döndürüyor). rand()Farklı bir tohumla başlatılmışsa , 8 ardışık çağrının farklı bir sıraya döneceğinin garantili olduğundan nasıl emin olabiliriz ?
RandomSeed

8
Sadece merak ediyordum. Neden bu numaraları kullanıyorsunuz ..4294967296)) * 36 + 1?
Mick

7
Bu biraz eski ama FLOOR()ikinci alt dize parametrelerini eklemem gerektiğine dikkat etmek isterim : substring('ABC … 789', floor(rand(@seed:= … )*36+1), 1), Bazı durumlarda, alt dize, 37'ye yuvarlandığında hiçbir karakterin seçilmemesine neden olmayacak olan 36.9 karakterini seçmeye çalışıyordu.
Phillip Dodson

4
Çoğaltılabilir bir dizgeyi rastgele çağıramazsınız. Ve kullanıyorsunuz çünkü kopyalar da mümkündür floor(). Bu sqlfiddle , kopyaların üç karakter uzunluğundaki dizeler için oluşturulduğunu gösterir.
Paul Spiegel

6
@EugenRieck Rakamlarınızı nasıl aldığınızı anlamıyorum ("ilk 2 ^ 32 yineleme"). Ancak bu kavramı çürütmek için yalnızca bir kopya örneğine ihtiyacım var. Kimlikler 193844ve 775771algoritmanız için aynı dizeyi T82X711( demo ) oluşturacaktır.
Paul Spiegel

114

Çarpışma olasılığı beni rahatsız etmez. Sadece rastgele bir dize oluşturun ve var olup olmadığını kontrol edin. Varsa, tekrar deneyin ve halihazırda atanmış çok sayıda plakanız yoksa bunu birkaç kez yapmanıza gerek kalmaz.

Saf (My) SQL'de 8 karakter uzunluğunda sözde rastgele bir dize oluşturmak için başka bir çözüm:

SELECT LEFT(UUID(), 8);

Aşağıdakileri deneyebilirsiniz (sözde kod):

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

Bu gönderi beklenmedik düzeyde dikkat çektiğinden, ADTC'nin yorumunu vurgulamama izin verin : Yukarıdaki kod parçası oldukça aptalca ve sıralı rakamlar üretiyor.

Biraz daha az aptalca rastgelelik için bunun yerine şuna benzer bir şey deneyin:

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

Ve gerçek (kriptografik olarak güvenli) rastgelelik için, RANDOM_BYTES()yerine kullanın RAND()(ancak daha sonra bu mantığı uygulama katmanına taşımayı düşünürdüm).


Çözümünüz için teşekkürler UUID ile ilgili bir sorum var. 8 karakter oluşturduğunuz id'nin kaç şansı tekrar tekrarlanır.
TR-Ahmed

1
@ user3099183 Resmi olarak , "çok düşük". 16 ^ 8, yaklaşık 4 milyar olası dizedir.
RandomSeed

23
UUID'nin ilk 8 karakterinin rasgele değil, zaman damgasına dayandığından sıralı olduğunu lütfen unutmayın.
ADTC

9 karakter uzunluğunda rastgele bir dize oluşturmak istiyorum ve 9kodunuzda kullandığımda , oluşturulan dizenin sonunda SELECT LEFT(UUID(), 9);her zaman -dokuzuncu karakter olarak bulunur. Sabittir. Neden?
Martin AJ

3
@MartinAJ çünkü dize bir uuid . SELECT LEFT(REPLACE(UUID(), '-', ''), 16);
Kısa

53

Sıralı tam sayıların MD5 (veya diğer) karmasını hesaplamaya, sonra ilk 8 karakteri almaya ne dersiniz?

yani

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

vb.

uyarı: Bir çarpışmadan önce kaç tane ayırabileceğiniz hakkında hiçbir fikrim yok (ancak bilinen ve sabit bir değer olacaktır).

düzenleme: Bu şimdi eski bir cevap, ama yine de ellerimde zamanla gördüm, bu yüzden gözlemden ...

Tüm sayıların şansı =% 2.35

Tüm harflerin şansı =% 0,05

MD5 (82945) = "7b763dcb ..." olduğunda ilk çarpışma (MD5 (25302) ile aynı sonuç)


2
İyi fikir, birincil anahtarda kullanabilir. Bunu gelecekteki projeler için akılda tutacak, teşekkürler!
funstein

2
Bunun sadece rakamlarla sonuçlanma ihtimali var
Mladen Janjetovic

9
Hiç rastgele değil.
paul

1
Otomatik artımlı kimliği kullanmak yerine, eklemenin yapıldığı tarih saatini kullanırsanız, bu da benzersizdir.
Javier La Banca

35

Rastgele bir dize oluşturun

İşte belirli bir uzunlukta rastgele bir dizi oluşturmak için bir MySQL işlevi.

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

Kullanım SELECT RANDSTRING(8)8 karakterlik bir dizeyi döndürmek için .

Sen özelleştirebilirsiniz @allowedChars.

Benzersizlik garanti edilmez - diğer çözümlere yapılan yorumlarda göreceğiniz gibi, bu mümkün değildir. Bunun yerine bir dize oluşturmanız, halihazırda kullanımda olup olmadığını kontrol etmeniz ve kullanılıyorsa tekrar denemeniz gerekir.


Rastgele dizenin zaten kullanımda olup olmadığını kontrol edin

Çarpışma kontrol kodunu uygulamanın dışında tutmak istiyorsak, bir tetikleyici oluşturabiliriz:

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
bu kabul edilen cevap olmalı, açık ve net bir şekilde benim için gayet iyi çalıştı, teşekkürler @ paddy-mann
Saif

Bence en iyi çözüm bu. Teşekkürler dostum!
Pronoy999

23

Geçerli karakterler olarak alfa sayısalları kullanmanın bir yolu:

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;

Benzersizlik garantisi olmadığını unutmayın. Bunu ayrıca kontrol etmeniz gerekecek.


7
bunun yerine floor (rand () * 36 + 1) kullanın. Aksi takdirde bazı sonuçlar 'kısa' olacaktır.
Fraggle

2
36 + 1 değil 35 + 1 olmalı! Aksi takdirde 8 karakterli bazı dizeler ve bazıları 7 karakterli diziler alacaksınız
BIOHAZARD

23

İşte rastgele bir dize oluşturmak için başka bir yöntem:

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


16

MySQL'in rand () ve char () işlevini kullanabilirsiniz:

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

Aşağıdakilerle rastgele bir alfasayısal dize oluşturabilirsiniz:

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

Bunu bir BEFORE INSERTtetikleyicide kullanabilir ve bir while döngüsünde kopya olup olmadığını kontrol edebilirsiniz:

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 ;

Şimdi verilerinizi şu şekilde ekleyin:

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

Ve tetikleyici, plate sütun .

( sqlfiddle demosu )

Bu, sütun NULL'lara izin veriyorsa bu şekilde çalışır. NULL OLMAMASINI istiyorsanız, varsayılan bir değer tanımlamanız gerekir.

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

İstediğiniz şey büyük harf alfanümerik değilse tetikleyicide başka herhangi bir rastgele dize üreten algoritma da kullanabilirsiniz. Ancak tetikleyici benzersizlikle ilgilenecektir.


İnanılmaz! Bu tam olarak istediğim şey. Sadece nasıl bir dizgeye dönüştürüldüğünü anlamak istiyorum. Neden bir güç var, ne yapmalı, sayı eklemek için vb. Her neyse, teşekkürler.
Akxe

@Akxe conv () , bir sayıyı alfasayısal bir dizeye dönüştürmek için kullanılabilir. pow(36,8)-1sayısal gösterimidir ZZZZZZZZ. Biz arasında rasgele bir sayı üretmek Yani 08-1' ve '36 ^ (den 0üzere 2821109907455) arasında bir alfanümerik dizeye dönüştürmek 0ve ZZZZZZZZunsing conv(). lapad () , 8 olana kadar dizeyi sıfırlarla doldurur.
Paul Spiegel

Siz bir dahisiniz efendim. Karakterlerin sürekliliği olmaması nedeniyle küçük harf eklemenin imkansız olduğunu hayal ediyorum? (91-96) İhtiyacım olduğundan değil, sadece merak ediyorum ...
Akxe

@Akxe conv()yalnızca 36'ya kadar tabanı destekler (10 hane + 26 büyük harf). Küçük harfleri dahil etmek istiyorsanız, bir sayıyı dizeye dönüştürmek için başka bir yola ihtiyacınız olacaktır.
Paul Spiegel

Uyarı: str_len> 13 için çalışmaz. 14'ten itibaren her zaman '3W5E11264SGSF' alırsınız. ;-)
Gerard H. Pille

6

Rastgele dizge oluşturmak için şunları kullanabilirsiniz:

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

Böyle bir şey alıyorsun:

353E50CC


5

8 rastgele sayıdan ve büyük ve küçük harflerden oluşan bir Dize için çözümüm şudur:

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

İçten dışa açıklandı:

  1. RAND 0 ile 1 arasında rastgele bir sayı üretir
  2. MD5 (1) MD5 toplamını hesaplar, 32 karakter af ve 0-9
  3. UNHEX (2) 'yi 00'dan FF'ye kadar değerlerle 16 bayta çevirir
  4. TO_BASE64 (3) 'ü base64 olarak kodlar, az ve AZ'den 22 karakter ve 0-9 artı "/" ve "+", ardından iki "="
  5. üç REPLACEs "/", "+" ve "=" karakterlerini (4) 'ten kaldırır
  6. LEFT (5) 'ten ilk 8 karakteri alır, rastgele dizenizde daha fazla veya daha az karaktere ihtiyacınız varsa 8'i başka bir karakterle değiştirin
  7. LPAD8 karakterden kısa ise (6) 'nın başına sıfır ekler; yine gerekirse 8'i başka bir şeye değiştirin

Harika, tam olarak
MySQL'de

4

Bir "karma" veya benzersiz bir dize oluşturmak için başka bir sütundaki verileri kullanıyorum

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

4

Alfabedeki 8 harf - Tümü büyük harf:

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

Bir kimliğiniz veya tohumunuz yoksa, tıpkı insert'deki bir değerler listesi için olduğu gibi:

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

2

Büyük ve küçük harfler ve rakamlarla rastgele 10 karakterlik bir dizi elde etmek için basit ve etkili bir çözüm:

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

1

"Rastgele" ancak tamamen öngörülebilir plakalarla sorun yaşıyorsanız, bir sonraki plaka numarasını seçmek için doğrusal geri beslemeli bir vardiya kaydı kullanabilirsiniz - tekrarlamadan önce her sayıyı gözden geçirmeniz garantidir. Bununla birlikte, biraz karmaşık matematik olmadan, her 8 karakterli alfasayısal dizeyi geçemezsiniz (36 ^ 8 (% 78) olası plakadan 2 ^ 41 elde edersiniz). Bunun alanınızı daha iyi doldurmasını sağlamak için, plakalardan (belki O) bir harf çıkararak size% 97'lik bir değer verebilirsiniz.


1

İhtiyaç duyduğunuz toplam karakter sayısını hesaba katarsak, tamamen benzer iki plaka üretme şansınız çok düşük olacaktır. Böylece, muhtemelen LUA'daki sayıları oluşturmaktan kurtulabilirsiniz.

36 ^ 8 farklı benzersiz numara plakanız var (2.821,109,907,456, bu çok fazla), zaten bir milyon plakanız olsa bile, zaten sahip olduğunuz bir tane oluşturma şansınız çok düşük, yaklaşık% 0,000035

Elbette, hepsi kaç tane sayı plakası oluşturacağınıza bağlı.


Doğru, SQL yerine gerçek oyunda yapmaya devam edeceğim. Çok teşekkür ederim.
funstein

1

Bu işlev, giriş uzunluğunuza ve aşağıdaki gibi izin verilen karakterlere göre bir Rastgele dizge oluşturur:

SELECT str_rand(8, '23456789abcdefghijkmnpqrstuvwxyz');

fonksiyon kodu:

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 ;

Bu kod, "Ross Smith II" tarafından gönderilen karışık dize işlevine dayanmaktadır.


Bu işlev rastgele benzersiz bir değer oluşturmayacaktır.
Faisal

1

Benzer karakterler 01oOlI hariç olmak üzere rastgele 10 basamaklı bir alfanümerik oluşturmak için :

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)

Bir kupon kodu oluşturmak için ihtiyacım olan şey tam olarak buydu . Bir kupon kodu formuna yazarken hataları azaltmak için kafa karıştırıcı karakterler kaldırılır.

Jan Uhlig'in parlak cevabına göre bunun birilerine yardımcı olacağını umuyor .

Bu kodun nasıl çalıştığına dair bir döküm için lütfen Jan'ın yanıtına bakın.


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 ;

Bu saklı yordamı kullanın ve her zaman aşağıdaki gibi kullanın

Call GenerateUniqueValue('tableName','columnName')

0

Benzersiz bir numara oluşturmanın kolay bir yolu

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


0

Benzer bir şey arıyordum ve eğer istenirse farklı bir tohum (karakter listesi) parametre olarak belirtebileceğiniz kendi sürümümü yapmaya karar verdim:

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

Şu şekilde kullanılabilir:

SELECT random_string(10, '')

Büyük ve küçük harflerin + rakamların yerleşik tohumunu kullanır. NULL ayrıca '' yerine değer olacaktır.

Ancak arama sırasında özel bir tohum belirtilebilir:

SELECT random_string(10, '1234')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.