Prevent creating duplicate entries in PHP - php

I want to randomly create a number of an user id, but it shouldn't be repeated/duplicated.
I wanted to ask if there is a good approach in general if my aim is to INSERT it into in a MySQL database? I don't want to create a new user. Its for another table.
I want to insert random data with random user id's to create test-comment entries users have made, but not I want to display different users. That's why I need it. It's not about autoincrementing with primary key in the main user table. I want to fill out a comment section
Example:
user_id: 54,34,30 randomy generated with PHP (mt_rand() function). Now I have about 1000 users I want to randomize, but there's still a chance it could be repeated at some point. So let's say now these are the values: 54,54,32
This means it will insert a same user twiche in further steps, where I INSERT this user id in the comment table.
So I just need another number randomly generated if it's already has been generated.

The best approach would be to create a GUID, rather than an integer. PHP has built-in methods to create these unique codes.
If you are inserting into a database, I would think that the most robust approach would be to create a primary key, and insert your entries one at a time. Since the DB call will error if you try to insert a duplicate ID, that's an appropriate place to check for an error and choose a different ID if you need to - although if you use a GUID, the chances of duplication are already negligible.
EDIT:
So if I understand what you are trying to do correctly, you want to create an array of random arrays of user ids, which are integers between 1-1000, where no two ids are repeated.
I am assuming that performances is not a big issue, since this sounds like test/dummy data. So the simplest way, in my opinion, would be to avoid having to test for an existing id on each id creation, and just shuffle your array.
So, you start with an array of 1000 ids, and then you loop through x number of times, shuffle the array, and slice off a random number of ids from the beginning of the array. Here is some code I have tested. It outputs what I think you want to create.
$ids = array();
$commentIds = array();
$numIds = 1000;
$numComments = 10;
for($i=0; $i<$numIds; $i++)
{
$ids[$i] = $i;
}
for($s=0; $s<$numComments; $s++)
{
shuffle($ids);
$num = mt_rand(1,10);
echo("rand:$num");
$commentIds[$s] = array_slice($ids,0,$num);
print_r($commentIds[$s]);
}
Is that what you mean?

If you have a specific number of users you want to add in, try just incrementing a digit and using that as the username. That way, they're all unique, and you don't have to force kill it after 30 seconds. This should be the easiest way of doing it, unless you need actually random (non-sequential) ids.

Related

Regenerate "random" MySQL query

I have a database with more than a million records. I'm trying to get the records in a randomized order. The database is filled with links to images and each image has an unique number. So I should be able to recreate the same "random" order for the next and previous buttons on the pictures?
Is there a way to come up with a query and save it on a cookie or session and reuse that to regenerate my random order?
Overall is it efficient because I don't want the load time to go high?
Any suggestion is awesome.
The easiest way for this is, put in another column in your database, index it properly, and give it a random integer. Then you can ORDER your table on this, and have it be stable. This will make all users have the same, but random, sequence.
EDIT: If you want each user to have their own sequence, this too is simple enough, as Alma Do said:
SELECT * FROM records ORDER BY RAND(17)
will always have the same ordering (as long as you don't change the database), and different from
SELECT * FROM records ORDER BY RAND(2308)
But it will not be fast.
The only alternative I can think of would use a lot of space: when you calculate a sequence for a user, store it in a table. This would require a two-column table of million rows per user.
According to MySQL manual page, you can specify parameter for RAND() function and so it will return random, but repeatable sequence:
If a constant integer argument N is specified, it is used as the seed
value, which produces a repeatable sequence of column values.
That means, you'll be able to have random order, but still same order across your prev-next pages.

Check if Random Exist in the database before inserting

i made a small code that generates different type of code, but i'll make it simpler,
i have a registration form submitted while submitting i collect some info about the user and i create for him a random, but i want this random to be unique for this user.
so i have 3 cases :
$code_random = rand(1000,9999);
if($code_random < 0){
$code_random = -$code_random;
}
$random = $fname.$code_random; //case 1
$random = $lname.$code_random; //case 2
$random = $fname.lname.$code_random; //case 3
But i want to create case 1 check if this random exist in the database, if it does use the second case if it does use the third case, before submitting the form and without displaying anything for the user.
Thanks for your help in advance.
Don't reinvent the wheel - SQL databases have two great ways of assigning unique IDs to every row.
1) Auto-incrementing primary key - goes up by one for every new row. Managed by the database, guaranteed to not use the same value for two rows by mistake. Nice and small and simple. http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
2) GUIDs (also known as UUIDs) - The algorithm used to generate GUIDs means that you'll never see the same one twice, ever. Over auto-incrementing integers, they have the advantage of being unpredictable, being generateable outside of the database and being meaningful outside of their database table context. http://www.php.net/manual/en/function.uniqid.php#94959 http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_uuid
If you really want to use a random integer, you can use the MySQL - rand() function for this
insert into users (id, ...) values (FLOOR(1000 + RAND() * (9999 – 1000)), ...)
There is a simple way of making infos unique: Create a unique index on the database column.
Then simply insert what you want and check if the database complains about violating the unique index. If this is the case, use one of your alternative queries and check again.
What if the last query still does not work?

unused number mysql

How can i get all of the records in a table that are out of
sequence so I know which account numbers I can reuse. I have a range
of account numbers from 50100 to 70100. I need to know which account
numbers are not stored in the table (not currently used) so I can use.
For instance say I have the following data in table:
Account Name
------ --------
50100 Test1
50105 Test2
50106 Test4
..
..
..
I should see the results:
50101
50102
50103
50104
because 50101-50104 are available account numbers since not currently in
table.
copied from http://bytes.com/topic/sql-server/answers/78426-get-all-unused-numbers-range
With respect to MYSQL and PHP.
EDITED
My range is 10000000-99999999.
My present way is using MySql query:
'SELECT FLOOR(10000000 + RAND() * 89999999) AS random_number FROM contacts WHERE "random_number" NOT IN (SELECT uid FROM contacts) LIMIT 1';
Thanks.
solution 1:
Generate a table with all possible accountnumbers in it. Then run a query similar to this:
SELECT id FROM allIDs WHERE id NOT IN (SELECT id FROM accounts)
Solution 2:
Get the whole id colummn into an array in php or java orso. Then run a for-loop to check if the number is in the array.
$ids = (array with all ids form the table)
for($i=50100;$i<=70100;$i++){
if(array_search($i, $ids) != -1){
$availableids[] = $i;
}
}
one way would be to create another table - fill it will all allowable numbers, then write a simple query to find the ones in the new table that are not in the original table.
Sort the accounts in the server, and find jumps in PHP while reading in the results. Any jump in the sorted sequence is "free for use", because they are ordered. You can sort with something like SELECT AccountNumber FROM Accounts SORT ASCENDING;.
To improve efficiency, store the free account numbers in another table, and use numbers from this second table until no more remain. This avoids making too many full reads (as in the first paragraph), which may be expensive. While you are at it, you may want to add a hook in the part of the code which deletes accounts, so they are immediately included in this second table, making the first step unnecessary.

Voting system questions

I'm having some trouble approaching a +1/-1 voting system in PHP, it should vaguely resemble the SO voting system. On average, it will get about ~100 to ~1,000 votes per item, and will be viewed by many.
I don't know whether I should use:
A database table dedicated for voting, which has the userid and their vote... store their vote as a boolean, then calculate the "sum" of the votes in MySQL.
A text field in the "item" table, containing the uids that already voted (in a serialized array), and also a numeric field that contains the total sum of the votes.
A numeric field in the "item" table, that contains the total sum of the votes, then store whether or not the user voted in a text field (with a serialized array of the poll id).
Something completely different (please post some more ideas!)
I'd probably go with option 3 that you've got listed above. By putting the total number of votes as another column in the item table you can get the total number of votes for an item without doing any more sql queries.
If you need to store which user voted on which item I'd probably create another table with the fields of item, user and vote. item would be the itemID, user would be the userID, vote would contain + or - depending on whether it's an up or down vote.
I'm guessing you'll only need to access this table when a user is logged in to show them which items they've voted on.
I recommend storing the individual votes in one table.
In another table store the summary information like question/poll ID, tally
Do one insert in to the individual votes table.
For the summary table you can do this:
$votedUpOrDown = ($voted = 1) ? 1 : -1;
$query = 'UPDATE summary SET tally = tally + '.$votedUpOrDown.' WHERE pollid = '.$pollId;
I'd go with a slight variant of the first option:
A database table dedicated for voting, which has the userid and their vote... store their vote as a boolean, then calculate the "sum" of the votes in MySQL.
Replace the boolean with an integer: +1 for an up-vote and -1 for a down-vote.
Then, instead of computing the sum over and over again, keep a running total somewhere; every time there is an up-vote, add one to the total and subtract one every time there is a down-vote. You could do this with an insert-trigger in the database or you could send an extra UPDATE thing SET vote_total = vote_total + this_vote to the database when adding new votes.
You'd probably want a unique constraint on the thing/userid pair in the vote tracking table too.
Keeping track of individual votes makes it easy to keep people from voting twice. Keeping a running total makes displaying the total quick and easy (and presumably this will be the most common operation).
Adding a simple sanity checker that you can run to ensure that the totals match the votes would be a nice addition as well.
serialized array: Please don't do that, such things make it very difficult to root around the database by hand to check and fix things, serialized data structures also make it very difficult (impossible in some cases) to properly constrain your data with foreign keys, check constraints, unique constraints, and what have you. Storing serialized data structures in the database is usually a bad idea unless the database doesn't need to know anything about the data other than how to give it back to you. Packing an array into a text column is a recipe for broken and inconsistent data in your database: broken code is easy to fix, broken data is often forever.

creating a unique key - most efficient way

I have two functions, makeKey() and keyExists().
makeKey() simply generates a 5 digit random alphanumeric key, keyExists() accepts this key as its only argument, and looks up in a table, returning true/false depending on whether it exists.
I need to do something very simple but I cannot figure out the quickest way of doing it.
I just need to make a key, and if it exists in the table, make a key again, and so on until a unique one is returned. I think a while loop will suffice?
Thanks and please forgive the rather basic question, I think I cooked my brain in the sun yesterday.
I’d use a do-while loop:
do {
$newKey = makeKey();
} while (keyExists($newKey));
This will generate a new key on every iteration until the key does not exist yet.
Any solution that relies on creating, then checking is going to have awful performance as the key space fills up. You'd be better off generating a unique key using an autogenerated column (identity or guid). If it needs to be alphanumeric, use a mapping function to transform it into the alphabet of your choice by selecting groups of bits and using them as an index into your alphabet.
Pseudo-code
alphabet = "ABCDE...789";
key = insert new row, get autogenerated key
alphaKey = "";
while (get n bits from key)
alphaKey += alphabet[bits]
done
echo alphaKey
my php is a little rusty, so consider this pseudo-code:
$key_exists = true;
while($key_exists) {
$key = generateKey();
$key_exists = checkKey($myKeysHash, $key);
}
// $key is now unique and ready to use
Why not use a built in php function like uniqid()?
You mention a table, so I'm wondering if you are storing these keys in a database? If so, your approach is going to have a race condition - you might check a key is OK to use right before another process uses that key.
A better approach is generate a possible key and then attempt to persist it - perhaps by performing an INSERT onto a table of keys and retrying with different keys until it succeeds.
I'll also assume you're using some sort of database.
Could you not use a unique auto-increment ID column in the database? It would remove the requirement to check if the key exists since the database engine will never assign the same ID twice.
However, you'd have to change the logic in your application rather than just coding up new functions.
Does it need to be random? Just increment a variable and store the next one to be used in another field.
while (keyExists($newKey = makeKey()));
Probably the quickest way of doing the check, if a key exists it will generate a new one. If you start having a lot of collisions/needing to check the database many times before getting a new unique key, you probably will want to rethink your makeKey() algorithm. Calls to the DB are expensive, the fewer calls you can make the faster and more efficient your script will be.
If you're not fixed on a 5-digit number, you could think about using a hash of your id + a name column.

Categories