I have just started to convert to mysqli due to the added security benefits. The main reason for converting to mysqli was the mysqli_multi_query function though. I had several long, complicated query's with a lot of JOINS in and when I found out about this function I thought I could make it simpler by breaking everything down into separate queries.
However, I have been unable to get the query to work as I want it to and the PHP manual isn't helping me.
Here's what I have so far;
$qry = "SELECT T.T_ID, T.name, T.pic, T.timestamp AS T_ts,
(SELECT COUNT(*) FROM track_plays WHERE T_ID = T.T_ID) AS plays,
(SELECT COUNT(*) FROM track_downloads WHERE T.T_ID = T_ID) AS downloads
FROM tracks T WHERE ID = '$ID';
";
$qry .= "SELECT S_ID, status, timestamp AS S_ts FROM status WHERE ID = '$ID';";
$qry .= "SELECT G_ID, gig_name, date_time, lineup, price, ticket, venue, G_pic, timestamp AS G_ts FROM gigs WHERE ID = '$ID'";
// Execute multi query
if (mysqli_multi_query($con,$qry)){
do {
// Store first result set
if ($result=mysqli_store_result($con)){
while ($row=mysqli_fetch_array($result)){
print_r($row);
}
}
}
while (mysqli_next_result($con));
}
This works fine and the array is printed as expected. However, i want to set a lot of variables for use later on. I won't list all of the variables but I have a few like this;
$S_ID = htmlspecialchars($row['S_ID']);
$T_ID = htmlspecialchars($row['T_ID']);
$G_ID = htmlspecialchars($row['G_ID']);
The variables are retrieved but due to the loop nature of the function PHP errors are given as well saying the $S_ID or $G_ID are undefined. $T_ID does not get an undefined error as it is the first query as is not looped over.
If you need any more information or I have not explained well enough just ask!
A while back ago i have had the same issues, and also for the same reason i have migrated from mysql to mysqli.
Sadly, it wasnt the best sollution for many cases, as i have realized on the way.
While implementing stuff with mysqli and multi query i still have had some issues that i had with mysql.
The solution i recommend, is to use views on your complicated querys.
it makes your coding and querys far less complicated.
I know it is not the answer you have been looking for, but give it a thought.
So far, every time I use a mysqli_multi_query, my do-while condition is:
while(mysqli_more_results($connection) && mysqli_next_result($connection));
You may like to replace your while statement and see if that helps.
If not, are you differentiating between each subsequent query when you are assigning these $S_ID, $G_ID variables? Are you inadvertently overwriting a variable with an empty $row[] value?
I also didn't see mysqli_free_result($result) in your code.
I'll even offer some error checking as a garnish.
preg_match_all("/(?:SELECT\s(.*?),\s.*?(?:;|$))/",$qry,$first_columnname);
if (mysqli_multi_query($con,$qry)){
do {
if ($result=mysqli_store_result($con)){
$query_identifier=array_shift($first_columnname[1]);
while ($row=mysqli_fetch_array($result)){
if($query_identifier)=="T.T_ID"){
//do something...
}elseif($query_identifier)=="S_ID"){
//do something...
}elseif($query_identifier)=="G_ID"){
//do something...
}
}
mysqli_free_result($result);
}
}
while(mysqli_more_results($con) && mysqli_next_result($con));
}
if($error_mess=mysqli_error($con)){echo "Error = $error_mess";}
Let me know if any of these small changes do the trick.
Related
So, I had this code working earlier today--and all of a sudden it decided to only start displaying the first result from the query. I cannot figure out what i've changed since then, I actually believe that I haven't changed anything... anyway... I've gone into the DB and altered the table so that all the "upgrades" meet the requirements to be displayed, and yet still only one result is being shown.
$sql = "SELECT id, name, cost, count(*) FROM upgrades
WHERE id NOT IN (Select upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid)
AND nullif NOT IN(SELECT upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid2)
AND prereq IN (SELECT upgrade_id FROM thehave8_site1.user_upgrades WHERE uid = :uid3)
;";
$que = $this->db->prepare($sql);
#$que->bindParam(':id', $id); //note the : before id
#$que->bindParam(':id2', $id);
$que->bindParam(':uid', $this->uid);
$que->bindParam(':uid2', $this->uid);
$que->bindParam(':uid3', $this->uid);
try {
$que->execute();
while($row = $que->fetch(PDO::FETCH_BOTH))
{
echo "<div class='upgrade' id={$row[0]}><p>{$row[1]}</p><p>{$row[2]}</p></div>";
}
} catch(PDOException $e) { echo $e->getMessage();}
Problem has been solved, though I'm not sure of the exact reason why, the count(*) being at the end of the query string was preventing the entire code from running properly
Aren't you missing some line of code that advances the result in the query to the next row? When I do loops through recordsets (slightly different than what you are doing but probably not much different) there is usually a MoveNext or something like that - I see nothing like that here.
I don't know this language you are using.
......
I am not being allowed to add a comment to your response so I will add it here..
....
Cool. You really looked like you knew what you were doing, far more advanced than anything I've written! New here also and didn't catch onto the tag system, thanks for pointing that out so I don't need to embarrass myself in future. Glad you've solved it. I think Count (*) would work if you included it as a subquery
SELECT FIELD1, FIELD2, (SELECT count (*) FROM ... ) AS FIELD3
FROM (ETC)
or if you just want its value in the recordset result, compute it ahead of time via query, and then include its value as a dummy/constant field in your select statement. Depending on the query plan in your query engine this may or may not be more efficient.
Or just wait to get Recordcount from your recordset.
I'm getting inconsistent results with the way I'm doing this so I thought I'd ask the geniuses here what you think. Here is what I'm doing...
$ccquerycount = "SELECT COUNT(*) as `count` FROM payments_cc_info WHERE user_id=$userid";
....
....
if ($row['count'] == "1") {
} else {
}
Is there a better way to design the if statement to achieve consistent results?
I am assuming that you are executing the query, retrieving the result set, fetching the row and extracting the value before the if statement (if not, then perhaps you need to do that first! Here is a start for PHP-MySql.
In case if you have already done that and forgot to mention this in your post (innocent until proven guilty I always say!! :) ), then could you provide us with more data on what are the different datasets when you got inconsistent results?
Try this
$ccquerycount = "SELECT * FROM payments_cc_info WHERE user_id=$userid";
$result = mysql_query($ccquerycount)
if (mysql_num_rows($result)==1) {
} else {
}
mysql_num_rows()
Get number of rows in result
Warning mysql_ extension is being deprecated . Instead, the MySQLi or PDO_MySQL extension should be used .
You can also add if condition inside of your mysql query like below.
SELECT
rating,
trade_service_id,
ifnull(round(sum(belonging_product_ratings.rating)/count(*),0),0) AS avg,
count(*) AS count
FROM
belonging_product_ratings WHERE trade_service_id != 0
GROUP BY
belonging_product_ratings.trade_service_id
other alternative is as below
select
BelongingProductRating.*,
User.*
from
belonging_product_ratings AS BelongingProductRating
LEFT OUTER JOIN
users AS User ON
IF( BelongingProductRating.rated_user_id != '$userID', BelongingProductRating.rated_user_id, BelongingProductRating.user_id) = User.id
You can say if condition inside mysql query is same as ternary if.
You can set query according to your php variable too.
I am sharing this code which i was ended up.
all you need to do is set it according to your table fields and conditions.
feel free to ask.
I need to grab data from two tables, but I know theres a better, more tidier way to do this. Is it some kind of JOIN i need?
I'll show you my code and you'll see what I mean:
if ($rs[firearm] != "") {
$sql_result2 = mysql_query("SELECT * FROM db_firearms WHERE name='$rs[firearm]'", $db);
$rs2 = mysql_fetch_array($sql_result2);
$sql_result3 = mysql_query("SELECT * FROM items_firearms WHERE player='$id'", $db);
$rs3 = mysql_fetch_array($sql_result3);
if ($rs3[$rs2[shortname]] < 1) {
mysql_query("UPDATE mobsters SET firearm = '' WHERE id ='$id'");
}
}
This question is clear, but your code example has alot of formatting issues and I cannot give you direct answer, based on your example code.
The reason, why your example is unclear, is because.. with what are you going to join the tables? From one table you are selecting by name='$rs[firearm]' and from another by player='$id'. You have to provide the hidden data, like $rs and also $id.
You should definitely read these about mysql join and mysql left join. But I will try to give you an example based on your code, with fixed syntax. (Keep in mind, that I'm no mysql join expert, I did not test this code and also I do not know the joining conditions.) And also, the system structure is unclear.
As I understood, this what your tables do, correct?
mobsters - Users table
items_firearms - Links from users table to items table
db_firearms - Items table
So basically, my example does this: It will have preloaded $rs value, from the users table. It will check, if there is a entry inside the links table and hook the result with them items table. However, if the links table or even the items table can return multiple entries, then this doesn't work and you need to loop your results in much more smarter way.
// I can only assume, that $id is the ID of the player
$id = 2;
// Since I dont know the $rs value, then Im going to make some up
$rs = array(
'id' => 33,
'firearm' => 'famas'
);
if ($rs['firearm']) {
$result = mysql_fetch_array(mysql_query("SELECT ifa.*, dbfa.* FROM `items_firearms` AS `ifa` LEFT JOIN `db_firearms` AS `dbfa` ON `ifa.shortname` = `dbfa.shortname` WHERE `ifa.player` = '$id'"));
if ($result['id']) {
mysql_query("UPDATE `mobsters` SET `firearm` = '' WHERE `id` = '$id'", $db);
}
}
It is pretty clear, that you are new to PHP and mysql.. So I think you should probably edit your question and talk about your higher goal. Briefly mention, what your application are you building..? What are you trying to do with the mysql queries..? Maybe provide the table structure of your mysql tables..? I'm sure, that you will get your questions votes back to normal and also we can help you much better.
NOTES
You have to quote these types of variables: $rs[firearm] -> $rs['firearm']
If you want to check if your $rs['firearm'] equals something, then there is a better way then $rs[firearm] != "". The most simple is if ($rs['firearm']) {echo 'foo';}, but will produce a notice message, when all errors reporting mode. You can use isset() and empty(), but keep in mind, that isset() checks whether the variable has been set.. Meaning, even if its false, then it has been set. empty() reacts to undefined and empty variable the same, without any messages.
Also, "" means NULL, so if you even need to use "", then use NULL instead...much neater way..
I strongly recommend to use mysql class. You can understand the basics behind that idea from this answer. This is gonna make things much more easier for you. Also, mysql class is a must-have when dealing with dynamic applications.
if ($rs3[$rs2[shortname]] < 1) { .. makes no sense.. Do you want to check if the value is empty? Then (simple): if (!$rs3[$rs2[shortname]]) { .. and a very strict standard: if (empty($rs3[$rs2[shortname]])) { ..
Also you have to quote your sql queries, see my examples above.
Is the last mysql query missing $db?
I'm having problems debugging a failing mysql 5.1 insert under PHP 5.3.4. I can't seem to see anything in the mysql error log or php error logs.
Based on a Yahoo presentation on efficient pagination, I was adding order numbers to posters on my site (order rank, not order sales).
I wrote a quick test app and asked it to create the order numbers on one category. There are 32,233 rows in that category and each and very time I run it I get 23,304 rows updated. Each and every time. I've increased memory usage, I've put ini setting in the script, I've run it from the PHP CLI and PHP-FPM. Each time it doesn't get past 23,304 rows updated.
Here's my script, which I've added massive timeouts to.
include 'common.inc'; //database connection stuff
ini_set("memory_limit","300M");
ini_set("max_execution_time","3600");
ini_set('mysql.connect_timeout','3600');
ini_set('mysql.trace_mode','On');
ini_set('max_input_time','3600');
$sql1="SELECT apcatnum FROM poster_categories_inno LIMIT 1";
$result1 = mysql_query($sql1);
while ($cats = mysql_fetch_array ($result1)) {
$sql2="SELECT poster_data_inno.apnumber,poster_data_inno.aptitle FROM poster_prodcat_inno, poster_data_inno WHERE poster_prodcat_inno.apcatnum ='$cats[apcatnum]' AND poster_data_inno.apnumber = poster_prodcat_inno.apnumber ORDER BY aptitle ASC";
$result2 = mysql_query($sql2);
$ordernum=1;
while ($order = mysql_fetch_array ($result2)) {
$sql3="UPDATE poster_prodcat_inno SET catorder='$ordernum' WHERE apnumber='$order[apnumber]' AND apcatnum='$cats[apcatnum]'";
$result3 = mysql_query($sql3);
$ordernum++;
} // end of 2nd while
}
I'm at a head-scratching loss. Just did a test on a smaller category and only 13,199 out of 17,662 rows were updated. For the two experiments only 72-74% of the rows are getting updated.
I'd say your problem lies with your 2nd query. Have you done an EXPLAIN on it? Because of the ORDER BY clause a filesort will be required. If you don't have appropriate indices that can slow things down further. Try this syntax and sub in a valid integer for your apcatnum variable during testing.
SELECT d.apnumber, d.aptitle
FROM poster_prodcat_inno p JOIN poster_data_inno d
ON poster_data_inno.apnumber = poster_prodcat_inno.apnumber
WHERE p.apcatnum ='{$cats['apcatnum']}'
ORDER BY aptitle ASC;
Secondly, since catorder is just an integer version of the combination of apcatnum and aptitle, it's a denormalization for convenience sake. This isn't necessarily bad, but it does mean that you have to update it every time you add a new title or category. Perhaps it might be better to partition your poster_prodcat_inno table by apcatnum and just do the JOIN with poster_data_inno when you need the actually need the catorder.
Please escape your query input, even if it does come from your own database (quotes and other characters will get you every time). Your SQL statement is incorrect because you're not using the variables correctly, please use hints, such as:
while ($order = mysql_fetch_array($result2)) {
$order = array_filter($order, 'mysql_real_escape_string');
$sql3 = "UPDATE poster_prodcat_inno SET catorder='$ordernum' WHERE apnumber='{$order['apnumber']}' AND apcatnum='{$cats['apcatnum']}'";
}
In some languages (ColdFusion comes to mind), you can run a query on the result set from a previous query. Is it possible to do something like that in php (with MySQL as the database)?
I sort of want to do:
$rs1 = do_query( "SELECT * FROM animals WHERE type = 'fish'" );
$rs2 = do_query( "SELECT * FROM rs1 WHERE name = 'trout'" );
There is no MySQL function like this for PHP, however there is a more advanced substitute for it.
Edit: For those of you who don't know what a query of queries is, it's exactly this and there's a purpose some people do it like this. Using an AND operator is ****NOT**** the same thing! If I want results where username='animuson' for one part of my script and then want all the results out of that query where status='1', it is not logical for me to run another query using an AND operator, it is much more logical to loop through the previous results in PHP. Stop upvoting things without reading the comments on why they weren't upvoted in the first place, that's just lazy. If you don't have a clue what's being talked about, you shouldn't be upvoting or downvoting in the first place.
Well, you may want to do this without touching the db:
while($t = mysql_fetch_array($rs1)){
if($t[name] == 'trout'){
echo 'This is the one we\'re looking for!';
break;
}
}
In PHP, it would be terribly inefficient. You would have to loop through each row and check that its name was trout. However, is there any reason you can't do
SELECT * FROM `animals` WHERE `type` = 'fish' AND `name` = 'trout'
in SQL? It would be much, much faster.
You can also do something like
select morestuff from (select stuff from table where a = b ) where c = d;
Use the AND keyword?
"SELECT * FROM animals WHERE type = 'fish' and name='trout'"
Also, you can use LINQ for php http://phplinq.codeplex.com/