PDO and executing code - php

Just a quick question around executing PDO statements.
Below is my query
$setDate = "INSERT INTO wl_datecheck (inputdate) VALUES (UNIX_TIMESTAMP(STR_TO_DATE($reportDate, '%Y%m%d')))";
Now, what I am doing is setting the query & connection as the variable $data as follows:
$data = $conn->query($setDate);
What I need to know, is does that ^^ alone execute or do I need to include
$data->execute();
The reason for asking is that I seem to be getting duplicate content from the INSERT statement & I'm not sure why

You are indeed doing it twice, you either use Query or Execute.
From the Docs:
PDO::query() executes an SQL statement in a single function call,
returning the result set (if any) returned by the statement as a
PDOStatement object.
For a query that you need to issue multiple times, you will realize
better performance if you prepare a PDOStatement object using
PDO::prepare() and issue the statement with multiple calls to
PDOStatement::execute().
http://us2.php.net/pdo.query

You can also simply check the result of the Insert statement by using rowCount()
$data = $conn->query($setDate);
if($data->rowCount() >= 1){
//echo "Inserted";
}else{
//echo "An error occurred while inserting";
//$arr = $data->errorInfo();
//print_r($arr);
}
And no need to call execute()

Related

Why does mysqli_result::free_result not work on mysqli_stmt::get_result

I have the following code:
$post_title = "Some dynamic POST data";
$stmt = $conn->prepare("SELECT * FROM `posts` WHERE title=? ");
$stmt->bind_param("s", $post_title);
$stmt->execute();
$rows = $stmt->get_result()->num_rows;
$stmt->get_result()->free_result(); // throws error: commands out of sync
$stmt = $conn->prepare("... some new condition");
$stmt->bind_param(...);
$stmt->execute();
$rows = $stmt->get_result()->num_rows;
I know I can simply use $stmt->free_result, but the php docs https://www.php.net/manual/en/mysqli-result.free.php mention you can use free_result on mysqli_result object as well so why can't we use it on mysqli_stmt->get_result(), which is a result object as well?
mysqli_stmt::get_result() is not idempotent. You can only call it once. If you call it again you will get an error:
Commands out of sync; you can't run this command now
This error has nothing to do with free_result() which you probably should not be using in the way you showed anyway.
You need to store the result in a variable and only then you can perform all the operations you want.
$stmt = $mysqli->prepare("SELECT ? ");
$stmt->bind_param("s", $post_title);
$stmt->execute();
$result = $stmt->get_result();
$rows = $result->num_rows;
$result->free_result();
I would also recommend that you don't ever use free_result().
Explanation:
When mysqli makes a call to MySQL server to execute a prepared statement, the server will produce a result set. This is not the outcome of the EXECUTE call, but the actual output of the SQL. By default, mysqli prepared statements are running in unbuffered mode, which means that upon execution PHP will not fetch the results from the server. You must use one of the functions to retrieve it from the MySQL server. You can do it row by row using fetch(), you can tell PHP to buffer the result set in internal memory using store_result() or you can ask PHP to buffer the result encapsulated in a mysqli_result object using get_result(). The connection line will be busy as long as there are pending rows on the MySQL server.
Once you fetch the results from MySQL, there is nothing else to read. If you try to read again, you will get OOS error mentioned above. This is why you can't call get_result() multiple times and expect the same result. Once the data is fetched to PHP, it's gone from the line, and is now stored in PHP memory. The prepared statement can of course be executed again and a new result set will be produced.
See also mysqli - Executing statements.

PHP 2 Prepared Statements Error

I have 2 prepared statements in function. After I get result from first, I need one field's value from this result to be used in second statement as bind_param() function's parameter. But I was getting error, until I found out about store_result() function and used it after first statement. So can you tell or give some reference to read, why is there need to use store_result() function and why this problem arises, during using 2 prepared statements.
I don't know if I am right, but in my opinion this happens because I am not closing first statement before starting second and maybe because of both are open, some error arises.
EDIT:
I found out some information, that somehow helps me to solve this problem
Command out of sync:
This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without calling mysql_use_result() or mysql_store_result() in between.
store_result() it self for using Transfers a result set from the last query.
Example :
$stmt = $mysqli->prepare("SELECT col1,col2 FROM tabel WHERE col1= ?")
$stmt->bind_param('s', $test);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($col1,$col2);
$stmt->fetch();
You can read it in here how to use prepared-statement.
You can read this documentation how to use mysqli prepared-statement.

PDO::query() run into "Cannot execute queries while other unbuffered queries are active."

Maybee some other have the same problem than me.
I run over the error:
Cannot execute queries while other unbuffered queries are active.
Consider using PDOStatement::fetchAll(). Alternatively, if your code
is only ever going to run against mysql, you may enable query
buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
on PDO. As in many threads mentioned the error can at be at least one of the following problems:
The query cursor was not closed with closeCursor() as mentioned here; Causes of MySQL error 2014 Cannot execute queries while other unbuffered queries are active
There are more than two querys with one statement like mentioned here: PDO Cannot execute queries while other unbuffered queries are active
A bug in mysql-driver as mentioned here: What is causing PDO error Cannot execute queries while other unbuffered queries are active?
In my case all above did not help and it took some time till i solved the problem. this was my code (pseudo-code):
$stmt->startTransaction();
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
$stmt->prepare('SELECT * FROM database');
$stmt->execute();
$aData = $stmt->fetchAll();
$stmt->closeCursor();
$stmt->query("USE sometable;");
After I changed it to:
$stmt->startTransaction();
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
$stmt->prepare('SELECT * FROM database');
$stmt->execute();
$aData = $stmt->fetchAll();
$stmt->closeCursor();
$stmt->exec("USE sometable;");
It worked for my. What is the difference between query and exec?
PDO::exec() - "Execute an SQL statement and return the number of affected rows"
PDO::query() - "Executes an SQL statement, returning a result set as a PDOStatement object"
Why in this case PDO::query() does not work? The cursor IS closed, when called.
While it could conceivably be true that you've encountered the mysql driver bug here, we can't be sure of that because you've not given us that information (what version of PHP are you using? Does it use mysqlnd => check with php -i | grep mysqlnd? What does the rest of your code look like?).
There are many other possible explanations for your problem. I suspect the issue is actually your failing to close all the cursors, and/or fetch all the results, because $stmt is being reused heavily:
Quoted directly from the PDO::query manual page:
If you do not fetch all of the data in a result set before issuing your next call to PDO::query(), your call may fail. Call PDOStatement::closeCursor() to release the database resources associated with the PDOStatement object before issuing your next call to PDO::query().
You call closeCursor on $stmt, that's true, but you've not closed all cursors that have been created by you:
//<-- what is $stmt here?
$stmt->startTransaction();
//no matter, you've reassigned it a PDOStatement instance
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
//Huh? You're preparing yet another query on an instance of PDOStatement?
$stmt->prepare('SELECT * FROM database');
//you're executing this one, though
$stmt->execute();
//and fetching all data
$aData = $stmt->fetchAll();
//and closing this last statement
$stmt->closeCursor();
But what about the first statement you assigned to $stmt (the stored procedure call)? That cursor isn't closed anywhere
Now for the major difference between PDO::query and PDO::exec. Again, quoting the manual:
PDO::exec() does not return results from a SELECT statement.
Whereas:
PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.
I came across this problem too. It is likely to be a bug. If we take the following code, then you will see how it fails with the message 'General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll().'
$pdo = new \PDO("mysql:host=localhost", "root", "");
$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query("USE test");
If you change $pdo->query("USE test"); to $pdo->exec("USE test"); it will work. If you change $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); to $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true); it will also work. I haven't been able to find a proper solution yet though.
I solve the issue with steps:
After from performed:
$stmt = db::getInstance()->prepare("CALL phones(:phone)");
I close the:
$stmt->startTransaction();
And after that, I open again the transaction to use the query below:
$stmt->prepare('SELECT * FROM database');
My solve it is: One statement to call the procedure "CALL phones(:phone)" and another to execute the query wtih "SELECT * FROM database".
That is it.
Be careful, This can also happen if you are trying to fetch a non SELECT query (Eg - UPDATE/INSERT/ALTER/CREATE)

Getting the results of a variable length prepared statement in MySQLi

I writing an accounting website which has quite a few MySQL statements in it. To prevent SQL injection I use prepared statements for any data which is put in by the user.
In order to prevent having to write the steps of preparing and binding statements I have the following function:
function executeSql($mysqli,$query_string,$params=null,$paramtypes=null){
$nr_params=strlen($paramtypes);
$query_type = substr($query_string,0,3);
$stmt = $mysqli->prepare($query_string);
$queryParams[] = $paramtypes;
$counter=1;
if($nr_params>1){
while($counter<=$nr_params){
$queryParams[$counter]=&$params[$counter-1];
$counter++;
}
} else {
$queryParams[1]=&$params;
}
// Actual binding of the statement. Taking into account a variable numbers of '?' in the query string.
call_user_func_array(array($stmt,'bind_param'),$queryParams);
// Execution of the statement
$stmt->execute();
// Part where i'd like to have a substitute for:
$result = $stmt->get_result();
return $result;
}
In the last part I'd like to return the result because then using the result I can treat each row. The problem is that the mysqlnd driver is not installed on the production server so the function $stmt->get_result() cannot be used. I tried to bind the result into variables but then again, every query returns a different number of columns.
Anyone has an idea how to tackle this?
So in summary (in response to the comments):
How can I retrieve a results object of an executed MySQLi statement while I cannot use $stmt->get_result();
Kind regards,
EJG
PS I know the code is not flawless, e.g. if strings are used as variables to bind to the statement but that is easily fixed.
UPDATE:
I came across the function $stmt->result_metadata(); Although supposedly the function name suggests only the meta data the php documentation states that:
"If a statement passed to mysqli_prepare() is one that produces a result set, mysqli_stmt_result_metadata() returns the result object"...

I Can Never Execute SQL-Safe Queries?

I am using the ODBC extension in PHP to connect to an SQL 2000 server. Here is what I am up against:
I can execute queries with odbc_exec() OR
I can execute queries with odbc_execute()
In my opinion, the differences between these two query executing methods are nearly as different as night and day:
odbc_exec() will execute a non SQL-safe query and return the results from the query
odbc_execute() is used in conjunction with odbc_prepare() to execute an SQL safe query on the database. However, odbc_execute() can only ever return a boolean, and therefore cannot be used to return the results from a SELECT statement, or to check how many rows were updated from an UPDATE or DELETE statement
Is this really the way this all works, or is there some way to escape values for use in odbc_exec() or to get the results back from odbc_execute()?
The PHP documentation doesn't seem to over any solutions for the above dilemma.
Thank you for your time.
The resource for the query you're running is returned by the odbc_prepare function, not odbc_execute.
These two blocks of code do the same thing:
$query=odbc_exec("SELECT * FROM table WHERE userinput=".$hopefully_escaped_user_input);
while($row=odbc_fetch_array($query) {
//do stuff with $row
}
$query=odbc_prepare("SELECT * FROM table WHERE userinput=?");
odbc_execute($query,Array($user_input);
while($row=odbc_fetch_array($query) {
//do stuff with $row
}
Prepared statements are used in conjuction with a resource that "points to" the prepared statement.
Imagine prepared statements as if they were a function/ procedure you defined in SQL and then you use the resource to "call" that function.
Example from here:
<?php
$res = odbc_prepare($db_conn, $query_string);
if(!$res) die("could not prepare statement ".$query_string);
if(odbc_execute($res, $parameters)) {
$row = odbc_fetch_array($res);
} else {
// handle error
}
?>

Categories