开发者

Custom Unique ID

Is there any way I could make my model ID (primary key) generated int开发者_Python百科o random unique 8 digits containing only numbers instead of the default auto increment? A client requested this specific 8-digits-number-only feature, so I can't argue much about the reasons.

I want to use the PHP uniqid but it's 13 digits and contains alphabets as well.

Any idea?

Thanks.

Update

I forgot to tell that I need the ID randomly generated each new record being saved.

Just want to ask the mechanism on generating the ID and then saving the ID (also the attributes). Do I have to check the database first for the randomly generated ID whether another same key already exists and then save the attributes or what?


Why dont you keep the auto increment but set it to start from 10000000 on your primary key instead of 1?

ALTER TABLE some_table AUTO_INCREMENT=10000000


Yes you can. I assume you are on MySQL, when talking about AI. Just do not set it as auto increment and insert the value as for the other columns. You can create a function or method, which will take up to 8 numbers randomly or in specific order (algorithm).

INSERT INTO model (id, name, value, etc) VALUES (87654321, 'My selected name', 'some price or text', 'etc').

Consider that INT(11) value may accept from -2147483648 to 2147483647. Which will fit you for numbers with 8 digits. If at later time the client request bigger numbers you may need to switch to BIGINT.

I use to set the Primary Keys as unsigned, which allows you to fit numbers between 0 and 4294967295.

For php function - generator of 8 digits:

<?php

mt_srand();
$id = mt_rand(10000000, 99999999);

?>

You can read more about mt_srand() and mt_rand() on php documentation. It is said that they are better than the srand() and rand().


Keep the ID, but pad it.

$id = 6;
$padded_id = sprintf("%013d", $id);
// This will print 0000000000006

That'll pad the $id so that it's 13 digits long.

Every time you need to display the ID use a function to convert it, like this.

function padId($id){
    return sprintf("%013d", $id);
}

Or you could make a row in your table called pad-id, then run this function when you create a record (along with mysql_insert_id (to get the ID just inserted)).


The best approach depends on a subtle aspect of your client's randomness requirement -- When they say random do they mean completely unpredictable or just hard to predict? I don't mean to sound like Clinton at the Lewinski trial, but what your client intends when they say random affects whether it will even be possible for you to meet the requirement.

If the client wants to hide user IDs (for some perceived security benefit) and make them virtually impossible to predict or reverse-engineer, then that is very difficult. If the client would be satisfied with just "hard" to predict (which I suspect), then you can do something simple, similar to the md5 approach (@Dotty). But md5 is not collision resistant. And even with the best, provably unique hash algorithms (which md5 is not), you'll have a collision problem if the number of users is large compared to the number of digits you are allowed for user ID's (8). You have about 27 bits to work with in the 8 decimal digits allowed. Which means you're likely to get a collision after 2^N/2 = 2^(27/2) which is about 10K users. So if your client's user list approaches 10K users, then even the best hash algorithm will spend a lot of time filtering out all the collisions. To solve this without filters and nondeterministic algorithms, just use a simple "Full Cycle" algorithm. Some will produce pseudo-random numbers (PRNs) that are guaranteed to be unique and guaranteed to fully span whatever range you're trying to cover (e.g., the set of all 8-digit positive integers). And if you ever need to reverse engineer the user registration sequence just rerun the full cycle PRN generator again with whatever initial value you used. And you can keep this initial value a secret, like a private key, if your client wants to make it slightly more difficult than easy for a hacker to reverse-engineer your user ID sequence.

Another question for your client is whether leading zeros are allowed in the user id. If so, (and the client's randomness requirements are liberal) then the simple Full Cycle algorithm on Wikipedia will work nicely for you. It could be distilled to 2 lines of PHP. Whatever algorithm you use, it might be good to actually generate the list of official 8-digit semi-random user IDs in a separate table, and then just "pop" the value from the top of the table (deleting that row) whenever you add a new user. The database memory requirements shouldn't be prohibitive and it will streamline the user experience, eliminating any delays and memory gobbling caused by sophisticated, nondeterministic, random number generators and uniqueness filters. Trying to create the user ID online, live, it's conceivable you could get into a perpetual loop with some hash algorithms stalling your user registration indefinitely. And this stall (due to perpetual collision) might not occur until user 1000 or 10000. In contrast, with the offline lookup table approach, you can easily add additional client-prescribed filters like eliminating IDs with leading zeros; in case the client never wants to see a user with the ID 1 (00000001). And you'd know in advance whether everything is going to always work, without any hangs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜