How can I execute multiple procedures continuously? - php

Here is my code:
$query = "CALL user_top_categories_score(?, 'ALL', 0, 1)";
$sth = $this->dbh->prepare($query);
$sth->execute([$user_id]);
$category = $sth->fetchAll(PDO::FETCH_ASSOC);
$query = "CALL user_top_tags_score(?, 'ALL', 0, 3)";
$sth = $this->dbh->prepare($query);
$sth->execute([$user_id]);
$tags = $sth->fetchAll(PDO::FETCH_ASSOC);
It throws this error:
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2014 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. in C:\xampp\htdocs\myweb\others\user.php:71 Stack trace: #0 C:\xampp\htdocs\myweb\others\user.php(71): PDO->prepare('CALL user_top_t...') #1 C:\xampp\htdocs\myweb\application\other.php(24): user->index() #2 C:\xampp\htdocs\myweb\index.php(152): require_once('C:\xampp\htdocs...') #3 {main} thrown in C:\xampp\htdocs\myweb\others\user.php on line 71
Also I've used closeCursor() right after fetchAll(), based on this solution. But sadly it throws a new error:
Warning: Packets out of order. Expected 1 received 9. Packet size=7 in C:\xampp\htdocs\myweb\others\user.php on line 72
Warning: PDO::prepare(): MySQL server has gone away in C:\xampp\htdocs\myweb\others\user.php on line 72
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2006 MySQL server has gone away in C:\xampp\htdocs\myweb\others\user.php:72 Stack trace: #0 C:\xampp\htdocs\myweb\others\user.php(72): PDO->prepare('CALL user_top_t...') #1 C:\xampp\htdocs\myweb\application\other.php(24): user->index() #2 C:\xampp\htdocs\myweb\index.php(152): require_once('C:\xampp\htdocs...') #3 {main} thrown in C:\xampp\htdocs\myweb\others\user.php on line 72
Any idea how can I fix the problem?
Noted1: Each of queries above work separately. I mean, when I call a single procedure, it works as well.
Noted2: Each procedure returns a result set. I mean there is a SELECT statement in those procedures.

You may have just one SELECT in your procedure, but the API doesn't know that. It has to assume you might have multiple result sets returned from your procedure, therefore fetchAll() alone doesn't close the cursor.
You have to keep calling nextRowset() until it has returned a false result, indicating that all results have been returned from this statement.
See also my answer to How can I use a stored procedure in a MySql database with Zend Framework? (I answered this in 2009!).

Well, in the case of Stored Procedure, the $result object is more complex. In the case of applying MVC, multiple source can load multiple call statements, and the cursor from the first $result can be in the next to the last element of the array (In thise case, the Result has no more elements, in other way, is set to false). For me, worked clear all stored result.
Code:
function clearStoredResults($mysqli_link){ #------------------------------------
while($mysqli_link->next_result()){ if($l_result = $mysqli_link->store_result()){ $l_result->free(); } } }
And finally:
function execQuery($sql){
global $conexion;
try {
$result=$conexion->query($sql);
while($row = $result->fetch_assoc()){
$new_array[] = $row; // Inside while loop
}
return $new_array;
} catch (Exception $e) {
echo $e->getMessage();
}
finally {
clearStoredResults($conexion);
}
}
I recomend to explore with care. You can use administrative tools form mysql or mariabd and php, to explore the effects.

Related

PDOException SQLSTATE[HY093] after upgrading to PHP 8.1

today I encounter an issue after upgrading from PHP 7.4 to PHP 8.1.
All the time I was using this code to establish an MySQL connection:
<?php
$kundencode=$_SESSION['kdnr'];
$i=0;
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr='$kundencode' ORDER BY rgnr DESC");
$q->execute([$_SESSION['id']]);
$res = $q->fetchAll();
foreach ($res as $row) {
$i++;
?>
This worked fine, but when using PHP 8.1 my system throws:
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /home/clients-de/public_html/rechnungen2.php:60 Stack trace: #0 /home/clients-de/public_html/rechnungen2.php(60): PDOStatement->execute(Array) #1 {main} thrown in...
I can't see any mistake!?
What's the difference here between PHP 7.4 and 8.1?
Thank you for help...
The change that you encountered is that before PHP 8, PDO's error mode was set to silent by default. If it encountered any errors, it would just ignore them. This has now changed to the exception mode; every time an error is encountered, an exception will be thrown. So the issue was there before, it just remained unreported.
About the actual issue: you should really read up about prepared statements, they will make your code a lot safer. You're not providing any placeholders for prepared variables in your query, but you are passing them in the following line (which results in the exception):
$q->execute([$_SESSION['id']]);
As far as I see, the session ID is completely unnecessary for your query, but you could pass your customer number as a variable. The following should fix your issue:
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=? ORDER BY rgnr DESC");
$q->execute([$kundencode]);
First of all, you shouldn't inline raw variables in query, use param binding.
Invalid parameter number: number of bound variables does not match number of tokens
This means that count of array passed into PDO::execute() method is different with count of params in query.
For your case, maybe this solution helps you:
// let's assume there is '5'
$kundencode=$_SESSION['kdnr'];
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=:kundencode ORDER BY rgnr DESC");
// pass $kundencode into query
$q->bindValue('kundencode', $kundencode);
// SELECT * FROM qi_rechnungen WHERE kdnr='5' ORDER BY rgnr DESC
$q->execute();
If you want to pass $_SESSION['id'] into query, you must specify it in query template explicitly
#vixducis : That's exactly what I finally did yesterday - and got it to work as desired:
$q = $pdo->prepare("SELECT * FROM qi_domains WHERE kdnr = ? AND aktiv = ? ORDER BY id DESC");
$q->execute([$_SESSION['kdnr'], 0]);
So let me thank you all for your kind support!

MySQL Update and Select in one statement

I am attempting to do an UPDATE and a SELECT in the same sql statement. For some reason, the below code is failing.
$sql = "UPDATE mytable SET last_activity=CURRENT_TIMESTAMP,
info1=:info1, info2=:info2 WHERE id = {$id};";
$sql .= "SELECT id, info1, info2 FROM myTable
WHERE info1 >=:valueA AND info2>:valueB;"
$stmt = $conn->prepare($sql);
$stmt->bindParam(":info1", $info1);
$stmt->bindParam(":info2", $info2);
$stmt->bindParam(":valueA", $valueA);
$stmt->bindParam(":valueB", $valueB);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
QUESTION: what might I be doing wrong? I have been spending hours on this issue knowing that it's probably a small error right under my nose.
Edited:
I obtained this error message when loading the page that contains the php code:
Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]:
General error' in ajaxCall.php:89 Stack trace: #0 ajaxCall.php(89):
PDOStatement->fetchAll(2) #1 {main} thrown in ajaxCall.php on line 89
I am using ajax to call the php page that contains the above code, and when I load the php page from the browser, I get the above error message.
Line 89 is: $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
Since you are running two queries, you need to call nextRowset to access the results from the second one.
So, do it like this:
// code
$stmt->execute();
$stmt->nextRowset();
// code
When you run two or more queries, you get a multi-rowset result. That means that you get something like this (representation only, not really this):
Array(
[0] => rowset1,
[1] => rowset2,
...
)
Since you want the second set -the result from the SELECT-, you can consume the first one by calling nextRowset. That way, you'll be able to fetch the results from the 'important' set.
(Even though 'consume' might not be the right word for this, it fits for understanding purposes)
Executing two queries with one call is only allowed when you are using mysqlnd. Even then, you must have PDO::ATTR_EMULATE_PREPARES set to 1 when using prepared statements. You can set this using:
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
Alternatively, you can use $conn->exec($sql), which works regardless. However, it will not allow you to bind any data to the executed SQL.
All in all, don't execute multiple queries with one call.

using LEAST in SQL query when using PHP PDO Prepared statements

i am trying to use this PHP PDO prepared statement to run an SQL Query:
$stmt = $pdo_conn->prepare("SELECT *, LEAST(:col_list) as num FROM callplandata WHERE number LIKE :number HAVING num != 0 ");
$stmt->execute(array(':col_list' => implode(',',$column_list), ':number' => '%'.$_POST["prefix"].'%'));
but its showing this error message:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1582 Incorrect parameter count in the call to native function 'LEAST'' in /home/integra/public_html/included_pages/call_tarrif_search.php:62 Stack trace: #0 /home/integra/public_html/included_pages/call_tarrif_search.php(62): PDOStatement->execute(Array) #1 /home/integra/public_html/index.php(119): include('/home/integra/p...') #2 {main} thrown in /home/integra/public_html/included_pages/call_tarrif_search.php on line 62
what am i doing wrong?
LEAST accepts 2 or more values and returns the least one.
You're passing a single value, that is the roots of the error.
PS: and as soon as you haven't explained the original issue - there is nothing to add here. Please don't ask "how to fix it" because we have no idea what you're trying to achieve.

Zend db with prepared statement doesn't fetch all data

First the guilty code:
$preparedGetData = $db->prepare("CALL getData(?)");
foreach($userSet as $r) {
$preparedGetData->execute(array($r['id_user']));
$rs = $preparedGetData->fetchAll();
$preparedGetData->closeCursor();
}
Explication
getData = stored procedure in mysql
$db = instance of Zend_Db_Adapter_Pdo_Mysql (using Zend version 1.10.0 )
Symptoms
When I leave out closeCursor in the second cycle I already get error:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: 2014 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.
But I am using fetchAll !!!
When I add the closeCursor the result arrives incomplete. Invoking CALL getData('3872') in query browser returns 1 row with 72 columns. The same done by the code above returns 1 row with only first 41 columns.
What I'm doing wrong?
Edit2: Semi-solution
Code updated to:
$preparedGetData = $db->prepare("CALL getData(?)");
foreach($userSet as $r) {
$preparedGetData->execute(array($r['id_user']));
$rs=array();
do {
try {
$partial_rowset = $preparedGetData->fetchAll(); // When I put fetchAll() after the end of the cycle, I get empty resultset.
} catch (PDOException $error) { // The PDOException doesn't get caught here. Why?
error_log($error);
} catch (Exception $error) {
error_log($error);
}
if ($partial_rowset) {
$rs=array_merge($rs,$partial_rowset);
}
} while ($preparedGetData->nextRowset());
}
Symptoms
Getting error:
PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error
Next exception 'Zend_Db_Statement_Exception' with message 'SQLSTATE[HY000]: General error' in /home/GIT/includes/Zend/Db/Statement/Pdo.php:294
on the line with fetchAll.
This error I can catch using generic exception.
With this code I get all 72 columns.
I perceive this nasty because I am deliberately catching generic exception and just turning it into log. Which I guess will also become an performance issue (the cycle runs about 10 000 times).
MySQL stored procedures may have multiple result sets. That is, you can run more than one SELECT query inside a stored procedure, and then iterate over these multiple result sets.
This complicates fetching because the whole result is really like an array of arrays of arrays (multiple result sets, each result set may have multiple rows, each row may have multiple columns).
But fetchAll() only fetches all the rows from one result set. So when you call a stored procedure, you need to force it to flush all result sets. That is, keep calling nextRowset() until that function returns null.
The Zend_Db API is modeled off of PDO, so you can see example usage of nextRowset() in the docs for PDOStatement::nextRowset().
Unfortunately, there is no such function like fetchAllRowsets(). You are left to do it yourself as a while loop.

Zend Framework is throwing a strange error in Firefox and IE about the PDO?

At work we are using Zend 1.10.7 and were getting a weird error:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[08P01]: <<Unknown error>>: 7 ERROR: bind message supplies 0 parameters, but prepared statement "pdo_stmt_00000015" requires 1' in /var/www/ZendFramework-1.10.7/library/Zend/Db/Statement/Pdo.php:228
Stack trace:
#0 /var/www/ZendFramework-1.10.7/library/Zend/Db/Statement/Pdo.php(228): PDOStatement->execute(Array)
#1 /var/www/ZendFramework-1.10.7/library/Zend/Db/Statement.php(300): Zend_Db_Statement_Pdo->_execute(Array)
#2 /var/www/ZendFramework-1.10.7/library/Zend/Db/Adapter/Abstract.php(468): Zend_Db_Statement->execute(Array)
#3 /var/www/ZendFramework-1.10.7/library/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query(Object(Zend_Db_Table_Select), Array)
#4 /var/www/ZendFramework-1.10.7/library/Zend/Db/Table/Abstract.php(1505): Zend_Db_Adapter_Pdo_Abstract->query(Object(Zend_Db_Table_Select))
#5 /var/www/ZendFramework-1.10.7/library/Zend/Db/Table/Abstract.php(1321): Zend_Db_Table_Abstract->_fetch(Object(Zend_Db_Table_Select))
#6 /var/w in /var/www/ZendFramework-1.10.7/library/Zend/Db/Statement/Pdo.php on line 234
Has any one ever seen this before? and if so what's the cause? it only does this in Firefox and IE 9. But chrome is fine, the site works.
Any thoughts? Too me, and my Google mind its one of my inserts or select statements, but again in chrome it works, selects, inserts and updates information in the database.
we are using PostgreSQL as a database
The PDO query is looking for a bound parameter, with this said there should be no reason why different browsers are giving different results unless the values passed to this query are dynamically generated -
If your query looks like this:
SELECT * FROM users WHERE id = ?
You need to ensure you bind one parameter.
$stmt->bindParam(1, $idValue);
If $idValue is the result of a function that for some reason returns NULL or the bindParam method call itself is wrapped in a conditional statement that only evaluate true on Christmas day you will have an exception like yours. This is because the value is missing when the statement is executed.
Edit: My guess is that the Array value here PDOStatement->execute(Array) is empty.

Categories