I'm using the function below to create a unique field that is prefixed with a letter.
Will this cause any problems if its used for transactions with many users?
The scenario is that this function is called inside a loop and if there are many users simultaneously using the system. Will this cause any errors?Is there a better way to do this?I'm using the GLAccountID as foreign key to the other tables.
function getID(){
global $db;
$max_gl = $db->get_var("SELECT MAX(GLAccountNumber) FROM sys_glaccount");
if($max_gl == null){
$max_gl = 1;
}else if($max_gl > 0){
$max_gl = $max_gl + 1;
}
return 'GLA'.$max_gl;
}
The table looks something like this, GLAccountNumber is the primary key and I set it to auto-increment.
There are ways to do this, but you shouldn't really. Seriously. This is heavy and dangerous and the developer after you will cry a bit at night.
Please consider using the accountNumber, and just adding the GLA whenever you retrieve it? This way you have the simple, quick and correctness of the auto-id, and can pretttify it when you want.
Another option is to make it a combined key, with your prefix in one column and the number in the auto-increment, although I don't see why you should want it.
In the end, if all you do is add three letters, you don't need to actually do it in the same field :)
You can actually get the account id in the format you want without a new row:
SELECT CONCAT('GL',GLAccountNumber) AS GLaccountID FROM `sys_glaccount`
Rather than making a whole new column just to be referenced...
Alternatively, if your intention is to avoid confusion with identical fields, you can use
SELECT g.GLAccountNumber FROM `sys_glaccount` g INNER JOIN `sys_glaccount2` g2 ON g2.GLAccountNumber=g.GLAccountNumber
Without the query getting confused without unique field names
Related
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.
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?
I have two databases I need to work with, db_site and db_forum (these are generic names, FYI).
db_site has a table called main-news, which has a forumurl field which holds a forum thread id and a views field which holds the current pageviews for the article entry in the database. db_forum has a table called forum_threads which has a tid field and a replies field.
I have two things I need to do, one using just the replies and another using the replies and the views. I assume once the former is figured out the latter won't be much more than adding some extra parts, so I'm concerned with the former for the time being.
Not sure how I should approach this since the two tables are in different databases. The login I'm using has access to both of them (AFAIK), so that isn't the problem, it's more of the syntax involved. Would what I'm looking to do be something like this, perhaps?
SELECT
db_forum.forum_threads.replies AS replies
FROM
`db_forum.forum_threads` AS f,
`db_site.main-news` AS s
WHERE
f.tid = s.forumurl
That's a rough guess, from what I can find online abut doing this type of query. Any help is appreciated. :)
First of all, you should indent your SQL code properly. That long line was almost unreadable.
SELECT
db_forum.forum_threads.replies AS replies
FROM
`db_forum.forum_threads` AS f,
`db_site.main-news` AS s
WHERE
f.tid = s.forumurl
Then, make use of your table aliases "f" and "s". You introduced them, so you have to use them:
SELECT
f.replies AS replies
FROM
`db_forum.forum_threads` AS f,
`db_site.main-news` AS s
WHERE
f.tid = s.forumurl
Finally, you should remove the unnecessary quoting:
SELECT
f.replies AS replies
FROM
db_forum.forum_threads AS f,
db_site.main-news AS s
WHERE
f.tid = s.forumurl
If the names of the fields are indicative of their function, then f.tid refers to an identity column while s.forumurl does not. Normally the s.formurl in this case would be a foreign key. Just a guess.
I am trying to create a Class-Inheritance design for products.
There is the base table that contains all the common fields. Then for each product type there is a separate table containing the fields that are for that product type only
So in order to get all the data for a product I need to JOIN the base table with whatever table that correlates to the product_type listed in the base table. Is there a way to make this query join on the table dynamically?
Here is a query to try to illustrate what I am trying to do:
SELECT * FROM product_base b
INNER JOIN <value of b.product_type> t
ON b.product_base_id = t.product_base_id
WHERE b.product_base_id = :base_id
Is there a way to do this?
No, there's no way to do this. The table name must be known at the time of parsing the query, so the parser can tell if the table exists, and that it contains the columns you reference. Also the optimizer needs to know the table and its indexes, so it can come up with a plan of what indexes to use.
What you're asking for is for the table to be determined during execution, based on data found row-by-row. There's no way for the RDBMS to know at parse-time that all the data values correspond to real tables.
There's no reason you would do this to implement Class Table Inheritance. CTI supports true references between tables.
You're instead describing the antipattern of Polymorphic Associations.
Make 2 queries:
First select < value of b.product_type > and then use it in the second one (the one that you have, but replace < value of b.product_type > with the result from the first one).
No. There would be little point even if it were possible, as the query optimiser would not be able to make a plan without knowing anything about the right- hand side of the join.
You need to construct the query using concatenation or similar, but make sure that you only use a valid table name to avoid injection attacks.
You can create a procedure that takes the table name as an argument and constructs a dynamic-SQL query. But it's probably easier to do this in your server-side code (PHP). But rather than make it a variable (and as suggested vulnerable to injection attacks), create separate classes for the different join combinations. Use another class (like a dispatcher) to determine the correct class to instantiate.
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.