游标状态无效,SQLExecDirect 中的 SQL 状态 24000
我需要在 PHP 中通过 ODBC 按顺序调用两个存储过程:
#run stored procedure 1
$query = "Shipped_Not_Shipped_Rep ".$_GET['rep_id'];
$result = odbc_exec($dbh, $query);
odbc_result_all($result);
#run stored procedure 2
$query = "Shipped_Not_Shipped_Account ".$_GET['account_id'];
$result = odbc_exec($dbh, $query);
odbc_result_all($result);
在第二次存储过程调用后,我在 PHP 中收到此错误:
警告:odbc_exec() [function.odbc-exec]:SQL 错误: [unixODBC][FreeTDS][SQL Server]无效 游标状态,SQL 状态 24000 in SQLExecDirect
如果我重新安排调用存储过程的顺序,则总是第二个出错。有没有办法在调用之间重置光标位置?这里有点不符合我的风格。
I need to call two stored procedures in sequence via ODBC in PHP:
#run stored procedure 1
$query = "Shipped_Not_Shipped_Rep ".$_GET['rep_id'];
$result = odbc_exec($dbh, $query);
odbc_result_all($result);
#run stored procedure 2
$query = "Shipped_Not_Shipped_Account ".$_GET['account_id'];
$result = odbc_exec($dbh, $query);
odbc_result_all($result);
I'm getting this error in PHP after the second stored procedure call:
Warning: odbc_exec() [function.odbc-exec]: SQL error:
[unixODBC][FreeTDS][SQL Server]Invalid
cursor state, SQL state 24000 in
SQLExecDirect
If I re-arrange the order I call the stored procedures, it is always the second that errors. Is there a way to, idk, reset the cursor position between calls? A little out of my element here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
对于使用 SQL Server 获得无效游标状态的人,可以尝试以下方法:
在存储过程或 SQL 脚本的顶部。
在这里找到:https://social.msdn.microsoft.com/Forums/en-US/f872382a-b226-4186-83c7-0d0fcadcd3eb/invalid-cursor-state?forum=sqldataaccess
我在 SQL Server 2017 中运行一些非常普通的 SQL 时遇到了这个问题
Something to try for people getting invalid cursor state with SQL server:
At the top of your stored procedure or SQL script.
Found here: https://social.msdn.microsoft.com/Forums/en-US/f872382a-b226-4186-83c7-0d0fcadcd3eb/invalid-cursor-state?forum=sqldataaccess
I had this problem just running some very average SQL in SQL Server 2017
打开数据库的两个句柄。 ODBC 可能将光标维护在句柄中。
Open two handles to the database. ODBC probably maintains the cursor in the handle.
我遇到了同样的问题,但是两个查询之间的 odbc_free_result($result) 为我完成了这项工作。
文档:
I ran into the same problem, but
odbc_free_result($result)
between the 2 queries did the job for me.Documentation:
我也发现了确切的问题。显然,这在免费 ODBC 驱动程序中很常见。这是我早上尝试将项目从 MySQL 迁移到 ODBC SQL Server 时感到头疼的问题。我终于找到了为我摆脱这个问题的方法。
出现此错误是因为先前结果集中仍然存在活动游标。通过确保在发出新记录集之前阅读整个第一个记录集(即使只使用其中的一部分),我能够在不使用断开连接/重新连接方法的情况下摆脱此错误。注意:我使用的是 PHP。
给我一个错误:
清除错误:
简而言之,请确保在移动到
下一个声明。
I found the exact problem as well. Apparently this is common with the free ODBC drivers. This has been my morning headache from trying to migrate a project from MySQL to ODBC SQL Server. I finally found what got rid of this for me.
This error shows up because an active cursor still exists from the previous result set. I was able to get rid of this error without using the disconnect/reconnect method by ensuring I read through the entire first record set (even if only using a partial piece of it) before issuing a new one. Note: I'm using PHP.
Gives me an error:
Cleared the error:
In short, make sure you completely read or fetch the data set before moving to the
next statement.
使用 PHP 中的 unixODBC 和 freeTDS 打开嵌套查询的解决方法是
如果您可以修改 odbc.ini,
使用相同的连接信息创建另一个配置节,但使用另一个节名称:
然后在代码中创建两个句柄,每个句柄对应一个数据源描述:
然后您可以在嵌套查询中使用句柄:
您可以嵌套得更深,但必须为每个级别创建一个 odbc.ini 条目。
它并不漂亮,但它对我有用,直到有多个光标可用。
A work around for opening nested queries using unixODBC and freeTDS in PHP
if you can modify to your odbc.ini create another configuration section using the same connection info but another section name:
Then in your code create two handles, one for each data source description:
Then you can use the handles in nested queries:
You could nest deeper but you have to create a odbc.ini entry for each level.
It ain't pretty but it works for me until multiple cursors are available.
尝试使用不同的游标 $result1 和 $result2 访问结果。
Try accessing the results using different cursors, $result1 and $result2.
只是为了澄清,调用 finish() 意味着您只是完成了当前查询及其结果,现在您可以安全地再次调用execute()。无需先再次调用prepare()。
我在 AIX 上使用 ODBC 驱动程序连接 DB2 SQL 数据库时遇到了这个问题。我认为 AIX 具有旧的 ODBC 驱动程序,也许是因为 Linux 上一切都很好。
无论如何,我做了一个返回一行的 SQL 查询,在 for 循环中一遍又一遍地执行,如下所示,并收到 24000 错误。
我的结论是,我必须调用 $sth->finish() ,以便我可以安全地再次调用 $sth->execute() ,否则我可能会收到“无效的游标状态。SQLSTATE=24000”错误消息。
这是因为我们必须确保在移动到下一条语句之前完全读取或获取所有数据集。$sth->finish() 向 DBI 表明您已完成
语句句柄。然后可以将其重新用于对execute()的调用。
我还发现我可以将提取放入while循环中,即使除了查询之外只返回一行。似乎尝试获取下一个不存在的行也使得该行可以重新执行。
两种解决方案都对我有用。 :)
Just to clarify that calling finish() means you are merely finished with the current query and its results and you can now safely call execute() again. No need to call prepare() again first.
I got caught by this one on AIX using the ODBC driver to a DB2 SQL database. I think it was AIX that had an old ODBC driver perhaps because things were fine on Linux.
Anyway, I did an SQL query that returns one row, over and over in a for loop as follows and got the 24000 error.
My conclusion is that I had to call $sth->finish() so that I could safely call $sth->execute() again, otherwise I could get "Invalid cursor state. SQLSTATE=24000" error message.
This is because we must make sure we completely read or fetch all the data set before moving to the next statement.$sth->finish() indicates to DBI that you are finished with the
statement handle. It can then be reused for a call to execute()
I also found that I could instead put the fetch in a while loop, even though only one row is ever returned but the query. It seems trying to fetch the next non-existent row also makes the sth resuable for an execute.
Both solutions worked for me. :)