I am using MySQL and I am defining a stored procedure like this:
delimiter ;;
Create procedure sp_test()
select * from name_table;
end
When I try to execute that procedure I get this error:
#2014 - Commands out of sync; you can't run this command now
What does this mean and what am I doing wrong?
From the reference manual section B.3.2.12 Commands out of sync:
B.3.2.12 Commands out of sync
If you get Commands out of sync; you can't run this command now in your client code, you are calling client
functions in the wrong order.
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.
This post from the MySQL forums has this to say:
I've solved that problem. I use MySQL-Fron instead MySQL Query
browser. And everything works fine.
Makes me think that it's not a server or database problem but a problem in the tool you're using.
In my case, I had the following structure in my stored procedure:
DELIMITER //
DROP PROCEDURE IF EXISTS processcolumns;
CREATE PROCEDURE processcolumns ()
BEGIN
(...)
END //
DELIMITER ;
CALL processcolumns ();
DROP PROCEDURE processcolumns;
The problem relies here: DROP PROCEDURE IF EXISTS processcolumns;
I removed the semi colon ; and replaced it with the delimiter // like this:
DROP PROCEDURE IF EXISTS processcolumns //
And it's now solved!
I was able to reproduce this error with MySQL and phpmyadmin:
#2014 - Commands out of sync; you can't run this command now
On this version of MySQL:
el#apollo:~$ mysql --version
mysql Ver 14.14 Distrib 5.5.34, for debian-linux-gnu (x86_64) using readline 6.2
With the following SQL run through the phpmyadmin query window:
use my_database;
DELIMITER $$
CREATE PROCEDURE foo()
BEGIN
select 'derp' as 'msg';
END $$
CALL foo()$$ <----Error happens here, with or without delimiters.
I couldn't get the error to happen through the MySQL terminal, so I think it's a bug with phpmyadmin.
It works fine on the terminal:
mysql> delimiter $$
mysql> use my_database$$ create procedure foo() begin select 'derp' as 'msg'; end $$ call foo() $$
Database changed
Query OK, 0 rows affected (0.00 sec)
+------+
| msg |
+------+
| derp |
+------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
I think the bug has something to do with changing the delimiters mid-query within phpmyadmin.
Workaround: Slow down there, cowboy, and run your SQL statements one at a time when using phpmyadmin. phpmyadmin is "single task bob", he can only do one job.
The possible reason is that mysql client in your code is not thread safe, i encountered the same error when I call mysqldb in python, I have one mysql interface, used in 2 threads, the error happens. In this situation, you need to create more mysql interfaces along with threads.
I fixed this issue on phpMyAdmin 4.8.6
Issue: https://github.com/phpmyadmin/phpmyadmin/issues/14614
Pull-Request: https://github.com/phpmyadmin/phpmyadmin/pull/15234
The patch: https://github.com/phpmyadmin/phpmyadmin/pull/15234/files#diff-de1b7e9dd5969db226563678c658ea67
The patch consists into and if mysqli_more_results
then a call to mysqli_next_result
delimiter ;;
Create procedure sp_test()
select * from name_table;
end ## no end here, must add ;; after end. should be
delimiter ;;
Create procedure sp_test()
select * from name_table;
end ;;
Suppose that when you created the stored procedure you stored it in database named mydatabase to CALL the procedure. Go to your localhost DB and:
CALL mydatabase.sp_test();
Where sp_test() is the name of your procedure.
You forgot to use the 'Begin' keyword, and during compilation MySQL is confused, this should work:
DELIMITER ;;
Create procedure sp_test()
BEGIN
select * from name_table;
END;;
DELIMITER ;
I also encountered this problem with a C API.
I found the solution with the last example above, which speaks of delimiters.
use my_database;
DELIMITER $$
CREATE PROCEDURE foo()
BEGIN
select 'derp' as 'msg';
END $$
CALL foo()$$
My code executes a stored procedure then tests the return.
I use correctly the mysql_free_result().
Since I have not added a select clause "into" in the procedure, this error occurred.
The last example above is in the same case.
I have deleted the select and since it's ok.
Alex
I just got the same error from phpMYadmin when calling a user function I'm working on.
mysql console says however:
ERROR 1054 (42S22): Unknown column 'latitude' in 'field list'
...which is absolutely correct, it was misspelled in the field list, so a statement was referencing an undefined variable.
I'd have to conclude that
#2014 - Commands out of sync; you can't run this command now
from phpMYadmin is a rather non-specific error, than in many cases, if not most, is just obscuring the real problem, and one should not spend too much time trying to make sense out of it.
You have this problem apparently because both statements are executing simultaneously . The only workaround I have found is to close the connection after the sp and execute the other statement on a new one. Read about it here.
This was happening to me because a function within an procedure gave a value back that wasn't allocated to a variable.
The solution was:
select function .... INTO #XX;
It seems there are multiple sources for this issue. None of the posted answers worked in my case, I found that in my case I had selects and updates on a table in my stored procedure, the same table had an update trigger which was being triggered and sending the procedure into an infinite loop. Once the bug was found the error went away.
I also reproduced the issue in the case where I had a select which was calling a function which modified the table. It makes sense that these types of recursive calls could create issues. The issues were solved by updating a tmp table and at the end updating the original table from the tmp table.
Related
HERE is my trigger query which is working fine when it is fired directly in mysql database,but when i use this query in wordpress then it doesn't work.
so can you please give me some solution that how can i run this query with wordpress?
drop trigger if exists table_1;
DELIMITER $$
CREATE TRIGGER table_1
AFTER
INSERT ON table_2
FOR EACH ROW
begin
INSERT INTO table_3 ( place_id, store_name, store_address) VALUES (new.place_id, new.store_name, new.vicinity);
end $$
DELIMITER ;
Thank you in advance.
If you want to create a trigger through wordpress you can't use the $wpdb->query() method as it doesn't support trigger creation queries. In fact the Wordpress wpdb API doesn't support this at all.
You'll have to expose the underlying mysqli API and use mysqli_multi_query by doing this:
mysqli_multi_query($wpdb->dbh, $your_trigger_query)
The mysqli_multi_query function uses the mysqli connection and does support the creation of triggers.
My sys admin is upgrading my PHP server from 5.2 to 5.5 . As a result, the mssql family of functions is gone and I have to update my code (it seems to either the odbc functions or sqlsrv functions). Unfortunately, neither seems to be working correctly for anything beyond simple queries.
I've reduced one of the problematic queries down to the following two variants (middle line added is the only change):
IF OBJECT_ID('tempdb..#i') IS NOT NULL BEGIN DROP TABLE #i END
SELECT 'value' as test
IF OBJECT_ID('tempdb..#i') IS NOT NULL BEGIN DROP TABLE #i END
CREATE TABLE #i (id INT primary key) INSERT INTO #i SELECT 405782
SELECT 'value' as test
When I try them in SQL Server Mangement Studio, both work fine and return one row. When I try the first one from PHP, it works fine and returns one row. However, when I try to execute the second query from PHP I get an unexpected result:
$SQL_query= '********'; //Second query
$serverName = '**********';
$connectionInfo = array( "Database"=>"*****","UID"=>"********","PWD"=>"*********");
$conn = sqlsrv_connect( $serverName, $connectionInfo);
$msg1=sqlsrv_errors(SQLSRV_ERR_ALL); // ""
if($conn){ //truthy
$result=sqlsrv_query($conn,$SQL_query);
if(sqlsrv_has_rows ($result)){$rows='true';}else{$rows='false';} //false
$msg2=sqlsrv_errors(SQLSRV_ERR_ALL); // ""
$row=sqlsrv_fetch_array($result,SQLSRV_FETCH_NUMERIC) //false
}
(The odbc functions were even worse, choking if the query contained a SET #var statement...)
So the result of the query is incorrect, but no errors are reported.
Can anyone explain this? You'd think if the range of queries that could be handled by these functions was somehow limited that it would be at least mentioned in passing in the PHP documentation for these functions.
For reference: Microsoft SQL Server Standard Edition 9.00.1406.00, PHP 5.5.19 x86 thread safety disabled, running on Windows.
Edit: Per Rob Farley's suggestion, I've confirmed that the ##OPTIONS are either identical or immaterial to reproducing the problem.
Depending on what driver you're using (freetds?), you could be finding that ANSI_NULLS (and other ANSI settings, such as QUOTED_IDENTIFIER) are set differently to what is expected, and this can affect things such as the creation of tables. Try passing in a query that tests those values, and you will quite probably find the problem.
The problem is that the client framework is confused by the row counts that are returned by default for every statement. When the first INSERT happens, it returns a row count of 1, making it appear as if this is a statement returning results, which it's not -- the row count may even get confused for the result itself. PHP isn't the only technology troubled by this; jTDS is another driver that has trouble (in the case of jTDS, it requires the row count). SET NOCOUNT ON suppresses this extra information:
SET NOCOUNT ON
IF OBJECT_ID('tempdb..#i') IS NOT NULL BEGIN DROP TABLE #i END
CREATE TABLE #i (id INT primary key)
INSERT INTO #i SELECT 405782
SELECT 'value' as test
My stored procedure executes 100% fine from the Management Studio, but when running through PDO with a try catch block I get the following exception message:
SQLSTATE[IMSSP]: The active result for the query contains no fields.
I have tried the classic SET NOCOUNT ON (this caught me out previously) to stop it returning row counts, and I've done various tests by removing sections of the SP until I have found which section the error lies in. I've also tried the PHP PDO nextRowset() with no luck.
The Stored Procedure:
I declare a cursor (shock, horror I know!) and iterate over some results, which itself caused no issues - but in reality this cursor must run various stored procedures itself for each fetch in the cursor, and when I introduce these stored procedures that is when the issues appear.
I have gone through the SPs inside the cursor and SET NOCOUNT ON on them in case that might be the issue, but no luck. One or two of these SPs have OUTPUTS but these are captured in variables accordingly.
Does anyone have any ideas? I don't wish to post any code of the project but some scenarios of commands I perform in the cursor block:
SELECT #varName = columnName FROM dbo.tableName
SET #varName = (SELECT columnName FROM dbo.tableName)
EXEC dbo.storedProcedure #outputVar OUTPUT
My best guess is the top example is the problem, but I am not knowledgeable to know. I would like to locate the error without removing these one by one as the actions performed by the procedure as a whole are difficult to roll-back on my test database and each line is important to getting correct output.
Thanks in advance for any help provided!
I have now managed to solve this! Hopefully the solution will help others who run into this error or similar.
The issue was that nested cursors (cursor inside cursor) were in use for the SQL Server stored procedure. My main procedure (called from PHP by PDO) opened a cursor and then ran other stored procedures inside that cursor that opened a cursor of their own.
This method works fine when running the query in SQL Server Management Studio, but calling from PHP via PDO fails.
While I know that using cursors is considered bad practice by most SQL buffs, unfortunately I inherited these stored procedures so I'm removing all blame from myself!
The actual solution was to replace the cursor in the originating stored procedure (the one called by PHP which in turn calls the other SPs) with a while loop using code like this:
DECLARE #loopTable table (id int IDENTITY(1,1), dataColumn)
DECLARE #id int
DECLARE #rows int
DECLARE #data int -- var to hold targeted data in the loop
INSERT INTO #loopTable (dataColumn)
SELECT dataColumn FROM dataTable
SELECT #rows = COUNT(1) FROM #loopTable
WHILE (#rows > 0)
BEGIN
SELECT TOP 1 #data = dataColumn, #id = id FROM #loopTable
// Do stuff with #data variable here
DELETE FROM #loopTable where id = #id
SELECT #rows = COUNT(1) from #loopTable
END
Problem solved, nightmare to find!
This question without an accepted answer raises a catastrophic problem with MySQL that I am experiencing on MySQL version 5.6.16 on Windows in a modified form.
The problem is easily reproducible: I include it here (copied from the above-linked question, but with changes applicable to my code):
$pdo = /* connection stuff here */
$sql = "call test();"; // call stored procedure - see below
$statement = $connection->query($sql);
do {
$rowset = $statement->fetchAll(PDO::FETCH_ASSOC);
if($rowset) {
// Do stuff with $rowset
}
} while($statement->nextRowset());
Here is the definition of the stored procedure test:
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`$$
CREATE PROCEDURE `test`()
BEGIN
SELECT 1; SELECT 2; SELECT 3; SELECT 4;
END$$
DELIMITER ;
The only difference between my code, and the above-linked code, is that I pack the SQL query into a stored procedure.
In my case, the while statement returns true four times, rather than three times (it should be just three times). After the fourth time, fetchAll(...) throws a SQLSTATE[HY000]: General error error.
Unfortunately, this problem is catastrophic. There is no other way with PDO to iterate to following rowsets other than using the nextRowSet() function. Therefore, I may revert to a previous version of MySQL in order to work around this issue.
I have found two links that seem to indicate this issue, listed here:
https://bugs.php.net/bug.php?id=67130 and
http://permalink.gmane.org/gmane.comp.php.devel/81518
I would appreciate a confirmation that this is, indeed, a bug with version 5.6.16 of MySQL on Windows. Even more, I would appreciate a workaround. Thanks.
I had same problem with PDO::nextRowset(), as it returns true even there are no more rowsets available, therefore when calling fetchAll(), it raises exception HY000. (tested on PHP 5.5.12 windows, Mysql 5.5.17 linux)
A workaround for this problem is to check number of columns with method PDO::columnCount() before fetching rowset. If it is non-zero, you have a valid rowset, and thus you could call PDO::fetchAll().
Even if PDO::nextRowset() reports true, columnCount() will report number of columns before moving to next rowset.
Example:
while ($objQuery->columnCount()) {
$tab[] = $objQuery->fetchAll(\PDO::FETCH_ASSOC);
$objQuery->nextRowset();
}
If the problem is being caused by multiple result sets, then maybe the best work around would be to find ways of avoiding multiple result sets in a single query.
For example, if the expected results are in the same format (which I expect they probably are because you intend to use the same code to deal with all of them) then you could potentially use UNION to compound the four queries together.
SELECT 1
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4;
Failing that, you can execute a separate query for each SELECT and hand the result off to a function to do the processing.
This is just the strangest thing and I'm not sure why or what is happening. Everything runs fine in SQL Server but results in errors when ran in PHP.
In PHP, I build a dynamic statement that contains one to many queries or statements. It looks like this:
begin try
begin transaction
-- statement 1
UPDATE table_name SET status = 1 WHERE things='stuff';
-- dynamic: to run after inserts
exec [dbo].[SP_TEST_2];
exec [dbo].[SP_TEST_3];
exec [dbo].[SP_TEST_9];
exec [dbo].[SP_TEST_14];
commit
select 'successful' as for_php_success_message
end try
begin catch
rollback
select error_number() as for_php_error_number
,error_severity() as for_php_error_severity
,error_state() as for_php_error_state
,error_procedure() as for_php_error_procedure
,error_line() as for_php_error_line
,error_message() as for_php_error_message;
end catch
This morning, someone came to me because the front page to all of this was throwing errors at them. Warning: mssql_query() [function.mssql-query]: message: The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION. This code has been untouched for several months and hasn't had any problems. The code in the stored procedures probably has changed since then.
I copied the code over to SQL Server Management Studio to test and everything ran fine from a direct copy and paste. No errors, no warnings, just successful.
Next, I looked up transactions online and changed rollback to if ##trancount>0 rollback and this did fix the transaction error; however - I had a new error from PHP:
Array
(
[for_php_error_number] => 50000
[for_php_error_severity] => 16
[for_php_error_state] => 1
[for_php_error_procedure] => SP_TEST_Record
[for_php_error_line] => 247
[for_php_error_message] => spTEST_Record: 515: Cannot insert the value NULL into column 'TEST_DATA', table 'tempdb.dbo.#IDs________________________________________________________________________________________________________________00000001D27E'; column does not allow nulls. INS
)
(still, a reminder: no errors are returned if I run the exact code in SQL Server Mgmt Studio)
The error involves a SP that is called at the end of each of the SP_TEST_# procedures listed in the dynamic query that PHP built. I cannot copy the SP code over to here because this is work stuff and I didn't write them so I'd really prefer to not have to paraphrase them, either, because they are huge and not formatted well. I will however, show the top of SP_TEST_RECORD where the error occurs (which isn't on line 247):
ALTER PROCEDURE [dbo].[SP_TEST_Record] (
#Test_ID real=0, #debug int=1, #create_entry int=0, #autoclose bit=0, #autodelete bit=0
)
AS
BEGIN
SET NOCOUNT ON;
declare #vtest_id real; set #vtest_id=#Test_ID
declare #vdebug int; set #vdebug=#debug
declare #vcreate_entry bit; set #vcreate_entry=#create_entry
declare #vautoclose bit; set #vautoclose=#autoclose
declare #vautodelete bit; set #vautodelete=#autodelete
declare #test_date datetime; set #test_date=getutcdate()
declare #ct int;
begin try
begin tran
if object_id('tempdb..#IDs') is not null drop table #IDs
CREATE TABLE #IDs (TYC_ID int not null, TYC_TYPE_ID int not null, TYC_ENV_ID int not null, TEST_DATA nvarchar(2000) null) ON [PRIMARY]
ALTER TABLE #IDs ADD PRIMARY KEY NONCLUSTERED (TYC_ID, TYC_TYPE_ID, TYC_ENV_ID)
insert into #IDs(TYC_ID, TYC_TYPE_ID, TYC_ENV_ID, TEST_DATA)
select TYC_ID, TYC_TYPE_ID, TYC_ENV_ID, TEST_DATA from SR_TESTING where TEST_ID=#vTest_ID
So - one thing I know... some how, my PHP transaction was being ended by something in one of the stored procedures that was called by the dynamic statement and that is cause of the transaction issue. There are transactions inside of those stored procedures.
But why don't I see the null insert error in SQL Server when I run the same exact code? If there's a null insert, there's a null insert... so why would it make a difference if it was called from PHP or not?
And less importantly, how was my transaction being ended by one of the stored procedures in the beginning?
Why was thetransaction ended by the SP's when the code was ran in PHP but not when it was ran in SQL Server?
Is there some execution-concurrency-order of operations-transaction hierarchy-something going on?
I didn't want to straight delete this question because it was, at the very least, a great learning experience for me. However, it was a very localized question. I figured out the answer a while ago so I can't remember the specifics...
It was definitely caused because of something happening in one of the stored procedures that were being called down the line. I was very surprised to find out that the error bubbled up that way, especially with the PHP. I guess error scope kind of played a part in it... the PHP took the first error it saw but running the code in SQL server allowed it to fail more gracefully (so I didn't see the error there). Dunno. Troubleshooting... when in doubt - go deeper, lol...