Simultaneous mysqli_stmt prepared queries - php

I have following code:
<ol>
<?php
$db = mysqli_connect("host","login","pass","dbase");
$stmt = $db->prepare("SELECT id,name FROM table1 WHERE faculty=?");
$stmt->bind_param("d",$fac);
$stmt->execute();
$stmt->bind_result($id,$name);
while($stmt->fetch())
{
echo "<li>$name:<ul>";
$stmt2 = $db->prepare("SELECT mac,ip FROM table2 WHERE uid=?");
$stmt2->bind_param("d",$id);
$stmt2->execute();
$stmt2->bind_result($mac,$ip);
while($stmt2->fetch())
{
echo "<li>$mac ($ip)</li>";
}
echo "</ul></li>";
}
?>
</ol>
I get the error Commands out of sync; you can't run this command now. I know that I cannot have multiple queries running at once, but I've read, that I can use $stmt->store_result(). The problem is, that it does not help in my case (I tried calling it just after $stmt->execute()). How can I get my code working? Is it possible to do it without storing the results of first query in an array?

A single query with a LEFT JOIN will work in this case:
SELECT `t1`.`id`, `t1`.`name`, `t2`.`mac`, `t2`.`ip`
FROM `table1` AS `t1`
LEFT JOIN `table2` AS `t2`
ON `t1`.`id` = `t2`.`uid`
WHERE `t2`.`uid` = ?
This query will return all four columns in one shot provided id in table 1 is uid in table 2.

Related

Query works in phpmyadmin but same query won't return in PHP script

This is NOT a duplicate. None of the already existing threads have the same problem as me.
I have a database that stores athlete performances. It contains sessions, each session has sets, each set has "tables" (such as 4x100m, 12x50m and so on), and each table has times. I also have a table for athletes. Each athlete has an ID, each time links with the athlete through the AthleteID. Every session, set, timetable and time also have each unique IDs, used to link them with each other.
I want to make it so that when passing a session ID, it will return all the athletes that have at least 1 time in that session. I made a page that gets requests and the session ID is passed as GET search data (will make it POST later on). The request system works fine, but the problem is in the query. To do it I used inner joins to connect each table. This is my query (it is not the fastest method, but that's for another thread):
$q = "SET #evID = " . $method['sessID'] . ";";
$q .= "SELECT `athletes`.* FROM `events`
INNER JOIN `sets` ON `sets`.`EventID` = `events`.`EventID`
INNER JOIN `timetables` ON `timetables`.`SetID` = `sets`.`SetID`
INNER JOIN `times` ON `times`.`TableID` = `timetables`.`TableID`
INNER JOIN `athletes` ON `athletes`.`ID` = `times`.`AthleteID`
WHERE `events`.`EventID` = #evID
AND `times`.`TimeID` IN(
SELECT MIN(`TimeID`)
FROM `times`
WHERE `TableID` IN(
SELECT `TableID`
FROM `timetables`
WHERE `SetID` IN(
SELECT `SetID`
FROM `sets`
WHERE `EventID` = #evID
)
)
GROUP BY `AthleteID`
)";
Every single time I ran that in phpmyadmin it returned all the athletes, and the data was correct. However, when I run it in my script, the query value is false (such as if there is an error). I tried debugging like this:
$r = $db -> query($q);
var_dump($q);
var_dump($r);
var_dump($db->error);
The query is returned just fine (only difference is lack of newline characters), and when I copy what's returned in phpmyadmin the data is just the same. The rest however:
bool(false)
string(228) "You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT `athletes`.* FROM `events` INNER JOIN `sets` ON `sets`.`EventID` = `...' at line 1"
Other users with the same problem have not really gone that far to find out if they're wrong, but I have. This post is not a duplicate, and I didn't find any solutions online. Could this be a problem with the amount of queries in a single string? (There is one for setting #evID and one for the actual selection). Please explain the solution and methods kindly as I'm only 13 and still learning...
As #NigelRen has suggested, please use parameterized prepared statement.
Assuming that
$sessionid is storing the value for EventID, and assuming that this variable is of integer type; and
$conn is the connection
Then for Mysqli, you can use:
//$q = "SET #evID = " . $method['sessID'] . ";";
$sql = "SELECT `athletes`.* FROM `events`
INNER JOIN `sets` ON `sets`.`EventID` = `events`.`EventID`
INNER JOIN `timetables` ON `timetables`.`SetID` = `sets`.`SetID`
INNER JOIN `times` ON `times`.`TableID` = `timetables`.`TableID`
INNER JOIN `athletes` ON `athletes`.`ID` = `times`.`AthleteID`
WHERE `events`.`EventID` = ?
AND `times`.`TimeID` IN(
SELECT MIN(`TimeID`)
FROM `times`
WHERE `TableID` IN(
SELECT `TableID`
FROM `timetables`
WHERE `SetID` IN(
SELECT `SetID`
FROM `sets`
WHERE `EventID` = ?
)
)
GROUP BY `AthleteID`
)";
$stmt = $conn->prepare($sql);
$stmt->bind_param("ii", $sessionid, $sessionid);
$stmt->execute();
$result = $stmt->get_result(); // get the mysqli result
$row = $result->fetch_assoc(); // fetch data
// do other things you want , such as echo $row['fieldname1'];

Using A PDO Prepared Statement On A Search Form Query - PHP [duplicate]

This question already has answers here:
How do I create a PDO parameterized query with a LIKE statement?
(9 answers)
Closed 10 months ago.
I have some images that are outputted onto a page with PHP from a MySQL database. The while loop that outputs them includes a join because it gets data from two database tables (an imageposts table and a users table).
With the current output a query is run, but because there is no user input it uses the following code:
<?php
// IMAGE GRID JOIN
$stmt = $connection->query("SELECT imgp.*, u.id, u.firstname, u.lastname
FROM imageposts AS imgp
INNER JOIN users AS u ON imgp.user_id = u.id");
while ($row = $stmt->fetch()) {
// from imageposts table
$db_image_id = htmlspecialchars($row['image_id']);
$db_image_title = htmlspecialchars($row['image_title']);
$db_image_filename = htmlspecialchars($row['filename']);
$db_ext = htmlspecialchars($row['file_extension']);
$db_username = htmlspecialchars($row['username']);
// from users table
$db_firstname = htmlspecialchars($row['firstname']);
$db_lastname = htmlspecialchars($row['lastname']);
?>
-- HTML OUTPUT
<?php } ?>
The Issue
I'm also setting up my first search form for the site, and when the images are outputted I want them to pull in the same information as above (in addition to the search query), but because it's a search form and has user input, I'm going to need to use a prepared statement, and I cannot get my head around how to approach this?
The search will take place on the image_title column of the imageposts table, so in terms of sudo code it would be:
$searchSQL = "SELECT * FROM `imageposts` WHERE `image_title` LIKE %$searchQuery% ";
where the $searchQuery is the value of a search input field.
But how do I integrate that with the query in the first section of this question, and also use a prepared statement for security?
Would the MySQL be this?:
"SELECT imgp.*, u.id, u.firstname, u.lastname
FROM imageposts AS imgp
INNER JOIN users AS u ON imgp.user_id = u.id WHERE image_title LIKE %$searchQuery%"
And if so, how do I make it secure in terms of the prepared statement on the $searchQuery?
Alternative 1:
$sql = "SELECT imgp.*, u.id, u.firstname, u.lastname
FROM imageposts AS imgp
INNER JOIN users AS u ON imgp.user_id = u.id
WHERE image_title LIKE CONCAT('%', ?, '%')";
$stmt = $connection->prepare($sql);
$stmt->execute([$searchQuery]);
Alternative 2:
$sql = "SELECT imgp.*, u.id, u.firstname, u.lastname
FROM imageposts AS imgp
INNER JOIN users AS u ON imgp.user_id = u.id
WHERE image_title LIKE ?";
$stmt = $connection->prepare($sql);
$stmt->execute(["%{$searchQuery}%"]);

Is it possible to use the AND clause in a MYSQL JOIN statement?

Im currently using PDO to make my database queries, i find that that the query doesnt run when i append the "AND IFC.location= :location" section of the query, is the problem arising from using an AND clause while im already using the query to JOIN two tables? (the 'tables' table and the 'IFC' table)
$location= '1';
echo "<pre>";
$sql="SELECT name from IFC,tables
WHERE IFC.tablename=tables.id AND IFC.location=:location
ORDER BY Numopinions DESC
";
$stmt= $dbh->prepare($sql);
$stmt->bindParam(":location", $location);
if($stmt->execute())
{
$rows = $stmt-> fetchAll();
print_r($rows);
}
Yes. Your query should work, but the proper syntax would use explicit JOIN:
SELECT name
FROM IFC JOIN
tables
ON IFC.tablename = tables.id AND IFC.location = :location
ORDER BY Numopinions DESC;
Is there a reason you think your query does not work?
Yes AND can be used in joins also. If you think your statement is not working, just try to use without prepare statement and see the result.

SQL / PHP - Optimize query inside a while loop

I have a fairly simple query:
$r = $dbh->prepare("SELECT user FROM this_users_rented WHERE user_by=:user LIMIT $offset, $rowsperpage");
$r->bindParam(':user', $userdata['username']);
$r->execute();
($offset and $rowsperpage is representing the offset of the list, based on the current page, and how many records there should be shown per page. (Example: 0,100))
This will gather all the data from this_users_rented where the user_by is = $userdata['username'];
I am running this query in a WHILE LOOP:
while($data=$r->fetch()):
//Get data from table: this_users_rented to print out in the while loop.
$stmt = $dbh->prepare("SELECT * FROM xeon_users_rented_stats WHERE urs_user=:user");
$stmt->bindParam(':user', $data['user']);
$stmt->execute();
$refStat = $stmt->fetch();
endwhile;
So, imagine that there is hundreds of records in the $r query - yielding hundreds of queries to be run (due to the lack of optimization of the $stmt query)
So my question is, how can I optimize the $stmt query?
You have a LIMIT clause on your user table so you could use following trick to overcome the MySQL limitation that you can't use a LIMIT clause in a subselect for the preparing of the statement:
$r = $dbh->prepare("
SELECT x.*
FROM xeon_users_rented_stats x
INNER JOIN (
SELECT
user_by
FROM this_users_rented
WHERE user_by = :user
LIMIT $offset, $rowsperpage
) t
ON x.urs_user = t.user_by
ORDER BY x.urs_user;"
);
$r->bindParam(':user', $userdata['username']);
$r->execute();
while($refstat=$r->fetch()){
// do what you want to do ...
}
This trick changes the subselect to a materialized derived table where you can use LIMIT.
Note:
Of course you should test the sql statement in a sql client first to make sure you get the data you need.

sql query from 2 tables and php

I have a simple php code that fetches data from a sql table.
TABLE 1
date_time
name
and another table which store name(same as TABLE1) and picture link.
TABLE 2
name
pic
PHP
$db = new PDO("mysql:host=$host;dbname=$dbname", "$username", "$password");
$sql = "select * from table1";
foreach ($db->query($sql) as $row) {
echo '<span class=name>'.$row['name'].'</span>';
echo "<img src=".$row['pic']." width='25px' height='25px'/>";
$db = null;
}
What i want is to be show the picture of the name from TABLE 2($row['pic']) according to name in TABLE 1.
How the sql statement and the php code should be in order to achieve this?
I run a sql statement in phpMyadmin and got it,but couldnt translate it in php code.
select table1.name,table2.pic from table1,table2 where table1.name=table2.name;
How about using JOIN:
SELECT table1.name, table2.pic
FROM table1
INNER JOIN table2
ON table1.name = table2.name
try this, use as keyword to alias your column names, so that you can get 'name' and 'pic' index in the loop.
select
table1.name as `name`,
table2.pic as `pic`
from table1, table2
where table1.name = table2.name;
a better way to do it use joins
select
`table1`.`name` as `name`,
`table2`.`pic` as `pic`
from `table1`
inner join `table2`
on `table1`.`name` = `table2`.`name`;

Categories