Multiple Nested query issue, possible to do it in sql? - php

I asked a question earlier on today regards to Running multiple queries in loop, and building multidimensional array This code that I wrote works, but it just doesn't feel right.
The main issue I was noticing is that to do what I needed to do involved nesting queries inside the loop over of the results of a previous query. This seemed to kick up a stink of errors once I did this more than once, and after a little google time it seems that this just isn't possible to do. So I broke the queries apart and used a for loop for the second query. But this just feels messy, I'm now running two loops and I'm sure there must be a better way of doing this. Some code:
// get all to be done by each user
$stmt = $conn->prepare("SELECT activityId FROM done WHERE userId=? ORDER BY number DESC");
$stmt->bind_param("s", $idq);
$stmt->execute();
$stmt->bind_result($aiddo);
$stmt->store_result();
$num_do = $stmt->num_rows;
while($stmt->fetch()) {
$activityId_do[] = $aiddo;
}
// get location information
for($i=0; $i<=$num_do; $i++) {
$act_done = $conn->prepare("SELECT fullAddress FROM `activity` WHERE (id=?)");
$act_done->bind_param("s",$activityId_do[$i]);
$act_done->execute();
$act_done->bind_result($fullAddress);
while($act_done->fetch()) {
$do_array[] = array(
"fullAddress"=>$fullAddress,
"type"=>"do"
);
}
}
So this code above is inside a while loop over the results on a query that gets all the users a user is following.
I was wondering if there is a better way of doing this, is it possible to use some kind of sql magic on it and do it all in the query?

Related

Simplest method to retrieve single (and only) row in SQLite using PDO

I have this PDO
$stmt = $db->prepare('SELECT * FROM channels WHERE id=:id');
$stmt->bindValue(':id', $id, SQLITE3_INTEGER);
$result = $stmt->execute();
What now is the simplest method to access the row returned using $row['column_name']?
I know that for sure the query will only ever return a single row as it's impossible to have more than 1 row with the same id so I am looking to keep the code as simple as possible to access that row.
Examples I've seen online are quite long and complex, using while loops to loop through rows etc. that I don't need.
It should be as simple as
$row = $stmt->fetch(PDO::FETCH_ASSOC);
The examples you've seen probably have something more like
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { ...
because they're designed to process a query result with multiple rows. But if you know you'll only ever have one row, you can just forgo the loop. Of course, this is assuming your query actually executed successfully and returned a result. It would be a good idea to at least check
if ($row) { ...
before you try to use it in your subsequent code.

How to get row count & loop through the result set

I've recently gotten over my bad habit of using the deprecated mysql functions in favor of mysqli, and I'm having some issues.
Right now, I'm using something similar to the following:
$query = $conn->prepare("SELECT * FROM table WHERE cid = ?");
$query->bind_param('i', $id);
$query->execute();
And this is where I get stuck. In order to loop through the result, I use:
while ($row = $query->get_result()->fetch_assoc()) {
//My code here
}
However, I need to determine the number of rows returned from the query before going through the results. To do this, I need to do the following:
$query->store_result();
$rows = $query->num_rows;
But I get errors when calling both get_result and store_result on the same query.. is there an easier way to do this? Am I overthinking things? I basically just want to determine if the result set has greater than x # of rows, and if so, loop through the results.
Thanks for any help.

Use bind_result to push into array

Is it possible to use bind_result and bind all of the columns into an array? The reason I ask is because I execute the code on lots of different tables and don't want to have to put each column in when the amount changes.
$stmt = $mysqli->prepare("SELECT * FROM " . $company . " WHERE `id` = ?");
$stmt->bind_param('s', $route);
$route = $_GET['routeid'];
$stmt->execute();
$stmt->bind_result($test);
Currently that's what my PHP looks like. Clearly it's wrong because you must bind them to something, I just need to know how to put the data into an array and bind it to that (hoping you can understand that poor explanation).
Thanks
PS. I've looked at the related answer and it only confused me. If someone could explain in a little more detail I'd appreciate it.
Why do you specifically want to use bind_result to do this when a more natural alternative already exists?
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
If fetch_assoc is not exactly what you want, other variations include fetch_row (numeric indexing) and fetch_object.
$stmt->bind_result($test['col1'], $test['col2']);
Continue adding $test['colX'] for however many columns you have.

Need to return/echo PHP PDO results from database

Well I've did do my research and I just can't seem to figure this out. So long story short, I'm using something like this:
btw, "(WebsiteInfo)" is just to sensor out my website/database information.
$SQL = new PDO('mysql:dbname=(WebsiteInfo);host=(WebsiteInfo);charset=utf8', '(WebsiteInfo)', '(WebsiteInfo)');
$SQL -> setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$SQL -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
Now, that's just currently just to start the database connect up. Which btw is mostly just a copy/paste code I found on this website too which is to prevent MySQL injection. Actually from this link How can I prevent SQL injection in PHP?. If there's anything wrong with it, I wouldn't mind advice or tips. As long as if it makes sense because I just started using databases probably not even a week ago so everything is new to me. Now there's this:
$Exicu = $SQL -> prepare("SELECT `tags` FROM `users` WHERE `user_id` = :a ") -> execute(array( ':a' => 16));
$Exicu is just there, because I have been trying to get the results from the query (if I said that right). Also the 16 is the users ID, but this will change often so that's why 16 isn't just tossed in the prepare statement. I've tried a lot of things but none of them worked. It either didn't work or made the PHP crash.
But anyway, things I already tried for $Exicu is $Exicu->rowCount(), $Exicu->bindParam, a while loop with $row = $Exicu->fetch(), $SQL->query($Exicu)->fetchAll();, a foreach loop with ($Exicu->fetch(PDO::FETCH_ASSOC) as $row), $Exicu->get_result(), echo PDO::query($Exicu);, echo mysql_result($Exicu), and just echo $Exicu. Yes I know, that looks pretty sloppy.
But none of these seemed to work to just show me the tags from the database of the specific user. So that's pretty much what I need help with. There's no problem when I use something like this echo mysql_result( mysql_query("SELECT (etc,etc)") ) but that doesn't have protection from MySQL injections.
I do my PDO queries like this:
$user_id = 16;
$query = $SQL->prepare('SELECT tags FROM users WHERE user_id = :uid');
$query->bindValue(':uid', $user_id, PDO::PARAM_INT);
$query->execute();
while ($row = $query->fetch(PDO::FETCH_ASSOC))
{
echo $row['tags'];
}
This will select data from the database, bind values in it safely and then we echo out the results.
The loop is needed to iterate through every result returned from the query. You can skip the looping part and create a variable like in the while statement, and use $row as an array with your results.
There is a thing called user defined function.
I am wondering why noone on this site ever using them.
For some reason everyone is ready to make a mile long single line of chained methods, instead of clean and concise function call:
$user_id = 16;
$tags = getone('SELECT tags FROM users WHERE user_id = ?',array($user_id));
there are many ways to create such a function. A quick and dirty one
function getone($sql, $data) {
global $SQL;
$stmt = $SQL->prepare($sql);
$stmt->execute($data);
return reset($stmt->fetch());
}
but of course it would be better to make set of functions and put them in a class

pdo prepared statement multiple execution?

I'm just getting to implement PDO in my site but I was wondering if it is possible to execute prepared statement multiple times?
$SQL = $dbh->prepare("SELECT * FROM user WHERE id=? AND users=?");
$SQL -> execute(array($id,$userid));
while($check = $SQL -> fetchObject()){
and then I would use a while loop for this SQL
Can I use the same $SQL for another execution within the while loop? So I don't have to type in the prepared statement again?
$SQL -> execute(array($id2,$userid2));
while($check2 = $SQL ->fetchObject(){
//while loops for second execution, but I'm not sure how it works cause
//its using the same $SQL?
}
}//this end bracket is for the first while loop
Yes, you can reuse the same prepared statement, but not how you have it in the question. What you are trying to do is essentially the same as doing this:
for ($i=0; $i<$some_number; $i++) {
echo $i."\n";
for ($i=0; $i<$some_number; $i++) {
// do something
}
}
The the second for loop moves the same pointer as the original one, so therefore the output from the above would simply be "0" indicating that the original for loop only happened once.
So in order to get around this, you will need to store the results of the first execute into an array and then iterate over it. That way you won't have to worry about any pointers
$SQL = $dbh->prepare("SELECT * FROM user WHERE id=? AND users=?");
$SQL->execute(array($id,$userid));
$checks = $SQL->fetchAll();
foreach ($checks as $check) {
$SQL->execute(array($id2,$userid2));
while ($check2 = $SQL->fetchObject(){
//while loops for second execution
}
}
This way, you are using exactly the same prepared statement (which is good) and the original $check variable is available to be used in the while loop.
However, with all that said, I have a strong hunch that you can probably get everything into one single SQL query without the need for looping over it like this.
Yes, it is possible. Prepare once, execute as many times as you need to.
Of course, I'm not sure why you're doing a SELECT in a loop... that typically doesn't make much sense.

Categories