I am working on the following script. Why am I always getting 0 using the COUNT(*) in my query against MySQL using prepared statement?
$num_query = "SELECT COUNT(*) FROM $tbl WHERE `tdisplay` = 1";
$stmt2 = $conn-> prepare($num_query);
$stmt2 -> execute();
$stmt2 -> store_result();
$rows = $stmt2->num_rows;
Related
Can someone explain why free_result after a while loop on a nested prepared statement causes bind_result to not update values as intended?
$stmt = $mysqli -> prepare("select col1 from table1 inner join ...");
$stmt -> bind_param("i", $id);
$stmt -> bind_result($col1);
$stmt -> execute() or die();
$stmt -> store_result();
$stmt2 = $mysqli -> prepare("select col2, col3 from table2 where col4 = ?");
$stmt2 -> bind_param("i", $col1);
$stmt2 -> bind_result($col2, $col3);
while ($stmt -> fetch()) {
$stmt2 -> execute() or die();
$stmt2 -> store_result();
while ($stmt2 -> fetch()) {
echo $col2 .",";
}
$stmt2 -> free_result(); // <== Works fine without this line
echo "---";
}
$stmt -> close();
$stmt2 -> close();
If I remove free_result, I get the expected output, let's say:
1,2,---3,4,5,---6,7,---
If I leave it, the last result of the first run on the parent loop repeats like so:
1,2,---2,2,2,---2,2,---
I can't find the answer in the docs ... It seems counter-intuitive since the results are retained instead of being freed.
Here's an executable example
As stated in the documentation for bind_result():
All columns must be bound after mysqli_stmt_execute() and prior to calling mysqli_stmt_fetch().
If you move the bind_result() call to the appropriate place it will work:
$stmt = $mysqli->prepare("select col1 from table1");
$stmt->execute();
$stmt->bind_result($col1);
$stmt->store_result();
$stmt2 = $mysqli->prepare("select col2, col3 from table2 where col4 = ?");
$stmt2->bind_param("i", $col1);
while ($stmt->fetch()) {
$stmt2->execute();
$stmt2->bind_result($col2, $col3);
$stmt2->store_result();
while ($stmt2->fetch()) {
echo $col2 .",";
}
$stmt2->free_result();
echo "---";
}
$stmt->close();
$stmt2->close();
The reason for this is that mysqli_stmt::free_result() asks mysqlnd to free up all result variables. The references are released, but neither the variables nor their values are not destroyed by PHP. They are just unbound.
You can either stop using mysqli_stmt::free_result() (which you probably should do anyway) or bind the result variables after every execution.
Following a tutorial, I execute SQL queries using PHP like so:
$query = $pdo -> prepare("SELECT id FROM Families WHERE family_name = ?");
$query -> bindValue(1, $family_name);
$query -> execute();
$query2 = $pdo -> prepare("SELECT * FROM Categories WHERE family_id = ?");
$query2 -> bindValue(1, $query); //ISSUE IN THIS LINE
$query2 -> execute();
My question: How do I take the result of the first query, the id, and put it as input in the second query?
You need to fetch the result, execute only runs the query in db, it does not get the values, try this which will return an array:
$result = $query->fetchAll();
If you know you only want one result, try:
$result = $query->fetch();
store the first query result in an object like
$result = $query->execute();
if ($result && $result->num_rows > 0)
{
$family = $Result->fetch_object();
$query2 = $pdo -> prepare("SELECT * FROM Categories WHERE family_id = ?");
$query2 -> bindValue(1, $family->id);
$query2 -> execute();
}
Please use limit 1 so that object don't return more than one id
$stmt1 = $pdo->prepare("SELECT id FROM Families WHERE family_name = ?");
$stmt1->bindValue(1, $family_name);
$stmt1->execute();
$family = $stmt1->fetch(PDO::FETCH_OBJ); //You can use fetch inorder to return 1 result for more use fetchAll();
//Here $family is now an object array
//Stored id in $family_id variable
$family_id = $family->family_id; //All the columns will save as properties now so you can easily access each of them
$stmt2 = $pdo->prepare("SELECT * FROM Categories WHERE family_id = ?");
$stmt2->bindValue(1, $family_id);
$stmt2->execute();
$stmt2->fetchAll(PDO::FETCH_OBJ); //Used fetchAll method because It's returning more than 1 result I guess
Try combining the Queries:
SELECT f.* FROM Families INNER JOIN Categories c on c.id = f.family_id WHERE c.family_name = ?
Fetch the result as Mohsen Nazari has stated
i need get result row count
$this-> db = new mysqli("localhost", "***", "***", "***") or die("Error ".mysqli_error($link));
$this-> db -> set_charset("utf8");
$query = "SELECT steps.id, steps.description, steps.sort, services.`name` AS service_name, services.short_name AS service_short_name, terminals.`name` AS terminal_name, terminals.short_name AS terminal_short_name FROM steps INNER JOIN instructions ON steps.page_id = instructions.id INNER JOIN services ON instructions.service_id = services.id INNER JOIN terminals ON instructions.terminal_id = terminals.id WHERE services.short_name = '{$service}' AND terminals.`name` = '{$terminal}' ORDER BY steps.sort";
if ($stmt = $this->db-> prepare($query)) {
$stmt -> execute();
$stmt -> store_result();
printf("row count: %d.\n", $stmt -> num_rows);
$stmt -> close();
}
it returns zero - 0 but there are some like 10-15 rows
Although "What I do incorrect" is an offtopic question for this site, the answer is:
Speaking of getting number of rows, you are doing everything correct.
The only cause for your troubles is some data/code inconsistency which you have to solve yourself.
Speaking of using prepared statements, you are using them wrong, adding variables directly into query while you ought to represent them with placeholders and bind later.
$stmt = $connection->prepare("SELECT id FROM articles WHERE position =? LIMIT 1");
$stmt-> bind_param('i',$call );
$stmt->execute();
$result = $stmt->fetch();
$oldpostid = $result;
$stmt->close();
I don't see anything wrong with it, but it is returning 1 or nothing. $call is set and integer. I tried this too:
$stmt = $connection->prepare("SELECT * FROM articles WHERE position =? LIMIT 1");
$oldpostid = $result['id'];
Assuming this is all working you need to bind the result variables as well. mysqli_stmt_fetch returns a boolean:
$stmt->execute();
$stmt->bind_result($id);
$stmt->fetch();
$oldpostid = $id;
You seem to be mixing mysqli & PDO. The first line is PDO
$stmt = $connection->prepare("SELECT id FROM articles WHERE position =? LIMIT 1");
The next line is mysqli
$stmt-> bind_param('i',$call );
Should be for PDO the unnamed variables in place holder Manual Example 4
$stmt-> bindParam(1,$call );
$stmt->execute();
OR using array
$stmt->execute(array($call));
I'm just trying to figure out how to determine the number of rows and then make that number display in the HTML.
My prepared statement looks like this:
if($stmt = $mysqli -> prepare("SELECT field1, field2, field3 FROM table WHERE id= ?ORDER BY id ASC"))
{
/* Bind parameters, s - string, b - blob, i - int, etc */
$stmt -> bind_param("i", $id);
$stmt -> execute();
/* Bind results */
$stmt -> bind_result($testfield1, $testfield2, $testfield3);
/* Fetch the value */
$stmt -> fetch();
/* Close statement */
$stmt -> close();
}
I understand that I'm supposed to first save the results, then use num_rows, like this:
$stmt->store_result();
$stmt->num_rows;
However, I'm running, and issue with the page bugging out when I put that code in there. I haven't even been able to get to the next step of how to display the number of rows
What am I missing in terms of calculating the number of rows inside the prepared statement, then how would I display it with a <?php echo '# rows: '.$WHATGOESHERE;?>
num_rows returns the number, you have to store it in a variable.
/*.....other code...*/
$numberofrows = $stmt->num_rows;
/*.....other code...*/
echo '# rows: '.$numberofrows;
So full code should be something like this:
$stmt = $mysqli -> prepare("SELECT field1, field2, field3 FROM table WHERE id= ? ORDER BY id ASC");
/* Bind parameters, s - string, b - blob, i - int, etc */
$stmt -> bind_param("i", $id);
$stmt -> execute();
$stmt -> store_result();
/* Bind results */
$stmt -> bind_result($testfield1, $testfield2, $testfield3);
/* Fetch the value */
$stmt -> fetch();
$numberofrows = $stmt->num_rows;
/* Close statement */
$stmt -> close();
echo '# rows: '.$numberofrows;
If you are only interested in the row count instead of the actual rows of data, here is a complete query block with a COUNT(*) call in the SELECT clause.
$conn = new mysqli("host", "user", "pass", "db");
$stmt = $conn->prepare("SELECT COUNT(*) FROM `table` WHERE id= ?");
$stmt->bind_param("s", $id);
$stmt->execute();
$stmt->bind_result($num_rows);
$stmt->fetch();
echo $num_rows;
Or if you want to know the row count before iterating/processing the rows, one way is to lump the entire resultset (multi-dimensional array) into a variable and call count() before iterating.
$conn = new mysqli("host", "user", "pass", "db");
$sql = "SELECT field1, field2, field3
FROM table
WHERE id= ?
ORDER BY id";
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $id);
$stmt->execute();
$result = $stmt->get_result();
$resultset = $result->fetch_all(MYSQLI_ASSOC);
echo "<div>Num: " , count($resultset) , "</div>";
foreach ($resultset as $row) {
echo "<div>Row: {$row['field1']} & {$row['field2']} & {$row['field3']}</div>";
}
*I have tested both of the above snippets to be successful on my localhost.
This works as of Feb 2020:
$number_of_records = $stmt->rowCount();
echo $number_of_records;
From php.net manual:
PDOStatement::rowCount() returns the number of rows affected by a
DELETE, INSERT, or UPDATE statement.
Here is an example from their website:
<?php
/* Delete all rows from the FRUIT table */
$del = $dbh->prepare('DELETE FROM fruit');
$del->execute();
/* Return number of rows that were deleted */
print("Return number of rows that were deleted:\n");
$count = $del->rowCount();
print("Deleted $count rows.\n");
?>
The above example will output:
Return number of rows that were deleted:
Deleted 9 rows.
Check out the example #2 here:
PHP.net
Use PDO::query() to issue a SELECT COUNT(*) statement with the same predicates as your intended SELECT statement, then use PDOStatement::fetchColumn() to retrieve the number of rows that will be returned. Your application can then perform the correct action.