I'm trying to loop through a stored procedure, called via prepared statement, in PHP. Hopefully it's not impossible. Here's my PHP code:
$database = new mysqli($server, $user, $pass, $db);
$stmt = $database->prepare("CALL thisShouldReturnEightResultSets (?)");
$stmt->bind_param("i", $id);
$stmt->execute();
do {
if ($res = $stmt->bind_result($myvar)) {
$stmt->fetch();
echo "*" . $myvar . "<br/>";
} else {
if ($stmt->errno) {
echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
} while ($stmt->next_result());
That should print like so:
* 4
* 16
* 7
etc...
... and then exit once it runs of out result sets. Instead I get:
* 4
Fatal error: Call to undefined method mysqli_stmt::next_result()
At first I tried get_result instead of bind_result, but that errored. Based on this I found that I don't have the mysqlnd driver installed. Iworked around that with bind_result. Now I need a work around for next_result which I'm guessing is part of the mysqlnd driver as well. What are my options here? Tech notes:
PHP Version 5.3.2-1ubuntu4.11
Thanks.
I don't think you can do this with a prepared statement, since you don't have the MYSQLND driver. You'll have to do it the old fashioned way, with escaping.
$id = $database->real_escape_string($id);
if ($database->multi_query("CALL thisShouldReturnEightResultSets ('$id')")) {
do {
if ($result = $database->store_result()) {
while ($row = $result->fetch_row()) {
echo "*" . $row[0] . "<br/>";
}
}
} while ($database->next_result());
}
bindResult does not like multiple results.
Use get_result() then fetch_assoc and store in an array,
Then use a foreach loop to output your results.
$res = $stmt->get_result();
$array[];
while($x = $res->fetch_assoc()){
$array[]=$x;
}
Related
I am trying to get both the results of my query and the row count wihtout having to make two trips the the DB if possible. I am using prepared statements in a procedural way. My code is as follows:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
So the above code works just fine and returns my results. What I want to do now is get the row count using this same statement but i don't want to have to write a brand new prepared statement. If I writer a separate prepared statement and use store_results and num_rows I get the row count but that would force me to have to write an entire new block of code and trip to db. I am trying to do something as follows but It throws and error:
$dbd = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($dbd, "SELECT * FROM Contacts WHERE First_Name = ?" )) {
mysqli_stmt_bind_param($dbd, "s", $val1);
if (!mysqli_stmt_execute($dbd)) {
echo "Execute Error: " . mysqli_error($dbconnection);
} else {
//do nothing
}
} else {
echo "Prep Error: " . mysqli_error($dbconnection);
}
$result = mysqli_stmt_get_result($dbd);
mysqli_stmt_store_result($dbd);
$rows = mysqli_stmt_num_rows($dbd);
The throws and error as if i can't run both get results and store results using the same prepared statement. Im simply trying to keep my code compact and reuse as much as possible. If i break the above out into two separat prepared statements it works fine, Im just wondering there is a way to just add a line or two to my existing statement and get the row count. Or do i have to write an entire new block of code with new stmt_init, stmt_prepare, bind_param, execute, etc...
I tried your code (and reformatted it a bit), but I can't get it to work when I use both store_result() and get_result(). I can only use store_result then bind_result().
So the alternative is to fetch all the rows and then count them:
Example:
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = mysqli_stmt_init($dbconnection);
if (mysqli_stmt_prepare($stmt, $sql) === false) {
trigger_error("Prep Error: " . mysqli_error($dbconnection));
return 1;
}
if (mysqli_stmt_bind_param($stmt, "s", $val1) === false) {
trigger_error("Bind Error: " . mysqli_stmt_error($stmt));
return 1;
}
if (mysqli_stmt_execute($stmt) === false) {
trigger_error("Execute Error: " . mysqli_stmt_error($stmt));
return 1;
}
$result = mysqli_stmt_get_result($stmt);
$rows = mysqli_fetch_all($result, MYSQLI_ASSOC);
$num_rows = count($rows);
print "$num_rows rows\n";
foreach ($rows as $row) {
print_r($row);
}
In my opinion, PDO is much easier:
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test", "xxxx", "xxxxxxxx");
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Contacts WHERE First_Name = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$val1]);
$num_rows = $stmt->rowCount();
print "$num_rows rows\n";
while ($row = $stmt->fetch()) {
print_r($row);
}
I'm trying to build a function that allows me to abstract the use of the mysqli functions in my code. Currently I have a working version for using standard SQL (no prepared statements).
function mySqlQueryToArray($con, $sql){
// Process SQL query
$result = mysqli_query($con, $sql);
if(mysqli_error($con)){
out($sql . "\n");
exit("ERROR: MySQL Error: " . mysqli_error($con));
}
// Put result into 2D array
$output = array();
while($row = mysqli_fetch_assoc($result)) {
array_push($output, $row);
}
return $output;
}
Now I'm trying to translate that code into something that can use prepared statements but my research has revealed that when using prepared statements you need to bind each column to a different variable using mysqli_stmt::bind_result which causes a problem because the point of the function is to work for an arbitrary SQL Query.
My main question is this: Is there a way to print out the entire output from a SQL query in a 2D array same as the function above does using prepared statements?
Here's my current code for using prepared statements, it has everything but the bind_result in there.
//Creates a MySQL Query, gets the result and then returns a 2D array with the results of the query
function mySqlQueryToArray($con, $sql, $params){
// Prepare SQL query
$stmt = $con->prepare($sql);
if(mysqli_error($con)){
echo "$sql=>\n" . print_r($params, true) . "\n";
exit("$sql=>\n" . print_r($params, true) . "\nERROR: MySQL Error: " . mysqli_error($con));
}
// Bind parameters
foreach($params as $param){
$type = "s";
if(gettype($param) == 'integer'){
$type = "i";
}
$stmt->bind_param($type, $param);
}
//execute query
$stmt->execute();
// Put result into 2D array
$output = array();
// ??? need to bind results and get them into an array somehow
//close prepared statement
$stmt->close();
return $output;
}
PDO turns out to be the answer. I feel like I should post the code I created to solve my problem. Thanks to #Don'tPanic for the tip.
function pdoQuery($sql, $params){
$db = new PDO('mysql:host=localhost;dbname=My_Database;charset=utf8', 'username', 'password', array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
try {
$stmt = $db->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $rows;
}catch(PDOException $ex){
echo "ERROR: SQL Error: $sql";
// logError("ERROR: SQL Error: $sql");
}
}
New to mySQL PDO. I have read other answers here and read tutorials and am finally taking the plunge. Problem is I cannot seem to output data. Hence, can someone assess my code to ensure it is correct? Also, is the system I am using to query the db efficient and clean and secure? thanks
$pdo --- the correct connection information is in this line but has been removed ---
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// SELECT sql query
try {
$thedate='2013-06-03';
$rotation=1;
$stmt = $pdo->prepare("SELECT * FROM sched_main_2013 WHERE thedate=:thedate AND rotation=:rotation");
$stmt->bindValue(':thedate', $thedate, PDO::PARAM_STR);
$stmt->bindValue(':rotation', $rotation, PDO::PARAM_INT);
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);
}
catch(PDOException $ex) {
echo $ex->getMessage();
}
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows[assignedRad] . "\n";
echo $rows[rotation] . "\n";
}
// close the connection
$pdo = null;
This code outputs nothing. No errors. Nothing at all.
By the way, the table exists and the SELECT * FROM works fine when I manually run the mySQL statement, so data does exist with this query.
Try
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows[assignedRad] . "\n";
echo $rows[rotation] . "\n";
}
To
while($rows = $stmt->fetch()) {
echo $rows['thedate'] . "\n";
echo $rows['assignedRad'] . "\n";
echo $rows['rotation'] . "\n";
}
Debug 01
Maybe you can try this to test whether you truly receive any data from database
print_r($stmt->fetchAll());
Instead of your while-loop
Debug 02
Try the simple query that you strongly believe there will be no SQL error for example:
SELECT * FROM sched_main_2013
Without any value binding.
Debug 03
Try another query with WHERE condition, but no binding
SELECT * FROM sched_main_2013 WHERE thedate='2013-06-03' AND rotation=1
You told that var_dump($row) gives you FALSE. The documentation says:
The return value of this function on success depends on the fetch type. In all cases, >FALSE is returned on failure.
Add the following line:
while($row = $stmt->fetch()) {
echo $row['thedate'] . "\n";
echo $row['assignedRad'] . "\n";
echo $row['rotation'] . "\n";
}
if($row === FALSE) {
var_dump($stmt->errorInfo());
die();
}
Further note: You originally named the return value of $stmt->fetch() $rows (plural) instead of $row. I'm not sure whether you know that the method will return a single row each time it is called.
What it have to be
$sql = "SELECT * FROM sched_main_2013 WHERE thedate=? AND rotation=?";
$data = array('2013-06-03', 1);
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
$rows = $stmt->fetchAll();
var_dump($rows);
$sql = "SELECT * FROM sched_main_2013";
$data = array();
$stmt = $pdo->prepare($sql);
$stmt->execute(array());
$rows = $stmt->fetchAll();
var_dump($rows);
If second query returns the rows while first doesn't - there is no data found.
If both returns no rows - then it is caused by bad database design which is clearly seen from the table name, which should never have a postfix like this
I'm new to mysqli, I wrote a function as below.
1 - I couldn't find a way for SELECT * query and having bind_result to assign each column value to the same name variable. (e.g. name column value of #row stores to $name)
I think bind_result() has no function on a SELECT * query?
2 - So I tried another option, to fetch all rows and assign them to appropriate variable manually through a loop. I think I should use $query->fetch_all() or $query->fetch_assoc() for looping but I encounter with this:
Fatal error: Call to undefined method mysqli_result::fetch_all()
or
Fatal error: Call to undefined method mysqli_result::fetch_assoc()
However I did a phpinfo() and saw mysqlnd was enabled and php version is 5.4.7 (running XAMPP v1.8.1)
And 3- what finally I did is below idea that doesn't work either.
function the_names($name)
{
global $db;
if($query = $db->prepare("SELECT * FROM users where name=?"))
{
$query->bind_param('s', $name);
if($query->execute())
{
$query->store_result();
if($query->num_rows > 1)
{
while($row = $query->fetch())
{
echo $row['name']; // Here is the problem
}
}
else
echo "not valid";
$query->close();
}
}
}
I need a way to store all fetched data as what bind_result() does, or having them in an array for later use, and it's much better to know both. tnx
One word to answer all your questions at once - PDO
It has everything you are trying to get from mysqli (in vain):
function the_names($name)
{
global $db;
$query = $db->prepare("SELECT * FROM users where name=?");
$query->execute(array($name));
return $query->fetchAll();
}
$names = the_names('Joe');
foreach ($names as $row) {
echo $row['name'];
}
Note the proper way of using a function. it should never echo anything, but only return the data for the future use
If your mysqli code doesn't have binding_param() you can just write code like below :
$mysqli = new mysqli("localhost" , "root" , "" , "database_name");
$result = $mysqli->query( "SELECT * FROM users where name=" . $name) ;
while ( $row = $result->fetch_assoc() ) {
echo $row["name"];
}
If you use binding_param() code , you also need to set bind_result()
$db = new mysqli("localhost" , "root" , "" , "database_name");
function the_names($name){
global $db;
/* Prepared statement, stage 1: prepare */
if (!($query = $db->prepare("SELECT * FROM users where name=?"))) { # prepare sql
echo "Prepare failed: (" . $db->errno . ") " . $db->error;
}
/* Prepared statement, stage 2: bind and execute */
if (!$query->bind_param("s", $name)) { # giving param to "?" in prepare sql
echo "Binding parameters failed: (" . $query->errno . ") " . $query->error;
}
if (!$query->execute()) {
echo "Execute failed: (" . $query->errno . ") " . $query->error;
}
$query->store_result(); # store result so we can count it below...
if( $query->num_rows > 0){ # if data more than 0 [ that also mean "if not empty" ]
# Declare the output field of database
$out_id = NULL;
$out_name = NULL;
$out_age = NULL;
if (!$query->bind_result($out_id, $out_name , $out_age)) {
/*
* Blind result should same with your database table !
* Example : my database
* -users
* id ( 11 int )
* name ( 255 string )
* age ( 11 int )
* then the blind_result() code is : bind_result($out_id, $out_name , $out_age)
*/
echo "Binding output parameters failed: (" . $query->errno . ") " . $query->error;
}
while ($query->fetch()) {
# print the out field
printf("id = %s <br /> name = %s <br /> age = %s <br />", $out_id, $out_name , $out_age);
}
}else{
echo "not valid";
}
}
the_names("panji asmara");
Reference :
http://php.net/manual/en/mysqli.quickstart.prepared-statements.php
This question already has answers here:
Call to undefined method mysqli_stmt::get_result
(10 answers)
Closed 9 years ago.
I am executing select query using mysqli ...
/** ------------ queries ---------- **/
$stmt = $mysqli->prepare("SELECT * FROM dept");
if(! $stmt)
{
echo "statement not prepared well";
}
else
{
echo $mysqli->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
// add else
else{
echo "Query is successfully executed but no result fetch";
}
if (!($res = $stmt->get_result())) {
echo "Getting result set failed: (" . $stmt->errno . ") " . $stmt->error;
}
/** ------------------------------- **/
#------result ----
var_dump($res->fetch_all());
#---------(/result)----
My problem is the execute() is working fine but cannot fetch the records ... The table has good amount of data in it ... it is showing "Query is successfully executed but no result fetch" and after it Fatal error: Call to undefined method mysqli_stmt::get_result()
What am I doing wrong .. ?
Break the following
if (!($res = $stmt->get_result())) {
to
$res = $stmt->get_result();
if( !$res ) {
Or rather to
$res = $stmt->get_result();
if( $res->num_rows == 0 ) {
The error(I didn't notice it earlier) is because
mysqli_stmt::get_result() is available only with mysqlnd.
You need to install/configure it following the guidelines here.
What am I doing wrong .. ?
You are using mysqli instead of PDO
Whole your code could be rewritten in these few lines using PDO:
$stmt = $pdo->prepare("SELECT * FROM dept");
$stmt->execute();
var_dump($stmt->fetchall());
without all these numerous if and echo.
And the difference will be even bigger when you start with prepared statements