I was wondering if anybody knew a good way to create a unique random integer id for a primary key for a table. I\'m using MySQL. The value has to be integer.
How you generate the unique_ids is a useful question - but you seem to be making a counter productive assumption about when you generate them!
My point is that you do not need to generate these unique id's at the time of creating your rows, because they are essentially independent of the data being inserted.
What I do is pre-generate unique id's for future use, that way I can take my own sweet time and absolutely guarantee they are unique, and there's no processing to be done at the time of the insert.
For example I have an orders table with order_id in it. This id is generated on the fly when the user enters the order, incrementally 1,2,3 etc forever. The user does not need to see this internal id.
Then I have another table - unique_ids with (order_id, unique_id). I have a routine that runs every night which pre-loads this table with enough unique_id rows to more than cover the orders that might be inserted in the next 24 hours. (If I ever get 10000 orders in one day I'll have a problem - but that would be a good problem to have!)
This approach guarantees uniqueness and takes any processing load away from the insert transaction and into the batch routine, where it does not affect the user.
If your're open to suggestions and you can implement it, use UUIDs.
MySQL's UUID()
function will return a 36 chars value which can be used for ID
.
If you want to use integer, still, I think you need to create a function getRandID()
that you will use in the INSERT
statement. This function needs to use random + check of existing ids to return one that is not used before.
Check RAND()
function for MySQL.
How about this approach (PHP
and MySQL
):
Short
number
for user_id (UNIQUE)
number
as user_id
Looks heavy? Continue to read.
Long:
Table:
users (user_id int UNIQUE)
Code:
<?php
// values stored in configuration
$min = 1;
$max = 1000000;
$numberOfLoops = 0;
do {
$randomNumber = rand($min, $max);
// the very insert
$insertedRows = insert_to_table(
'INSERT INTO foo_table (user_id) VALUES (:number)',
array(
':number' => $randomNumber
));
$numberOfLoops++;
// the magic
if (!isset($reported) && $numberOfLoops / 10 > 0.5) {
/**
* We can assume that at least 50% of numbers
* are already in use, so increment values of
* $min and $max in configuration.
*/
report_this_fact();
$reported = true;
} while ($insertedRows < 1);
$min
, $max
, 0.5
) are just for explanation and they have no statistical meaning.insert_to_table
and report_this_fact
are not build in PHP. The are also as numbers just for clarify of explanation purposes.You can use an AUTO_INCREMENT
for your table, but give the users the encrypted version:
encrypted_id: SELECT HEX(AES_ENCRYPT(id, 'my-private-key'));
id: SELECT AES_DECRYPT(UNHEX(encrypted_id), 'my-private-key');
In response to: "Because I want to use that value to Encode to Base62 and then use that for an id in a url. If i auto increment, it might be obvious to the user how the url id is generated."
If security is your aim then using Base62, even with a "randomly" generated number won't help.
A better option would:
AUTO_INCREMENT
AUTO_INCREMENT
is going to be your best bet for this.
Here are some examples.
If you need to you can adjust where the increment value starts (by default it's 1).