Generating a random & unique 8 character string using MySQL

funstein picture funstein · May 24, 2013 · Viewed 259.6k times · Source

I'm working on a game which involves vehicles at some point. I have a MySQL table named "vehicles" containing the data about the vehicles, including the column "plate" which stores the License Plates for the vehicles.

Now here comes the part I'm having problems with. I need to find an unused license plate before creating a new vehicle - it should be an alphanumeric 8-char random string. How I achieved this was using a while loop in Lua, which is the language I'm programming in, to generate strings and query the DB to see if it is used. However, as the number of vehicles increases, I expect this to become even more inefficient it is right now. Therefore, I decided to try and solve this issue using a MySQL query.

The query I need should simply generate a 8-character alphanumeric string which is not already in the table. I thought of the generate&check loop approach again, but I'm not limiting this question to that just in case there's a more efficient one. I've been able to generate strings by defining a string containing all the allowed chars and randomly substringing it, and nothing more.

Any help is appreciated.

Answer

RandomSeed picture RandomSeed · May 24, 2013

I woudn't bother with the likelihood of collision. Just generate a random string and check if it exists. If it does, try again and you shouldn't need to do it more that a couple of times unless you have a huge number of plates already assigned.

Another solution for generating an 8-character long pseudo-random string in pure (My)SQL:

SELECT LEFT(UUID(), 8);

You can try the following (pseudo-code):

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

Since this post has received a unexpected level of attention, let me highlight ADTC's comment : the above piece of code is quite dumb and produces sequential digits.

For slightly less stupid randomness try something like this instead :

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

And for true (cryptograpically secure) randomness, use RANDOM_BYTES() rather than RAND() (but then I would consider moving this logic up to the application layer).