无效的游标状态,SQLExecDirect中的SQL状态24000

时间:2009-11-17 23:13:08

标签: php sql-server stored-procedures odbc cursor

我需要通过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中   SQLExecDirect的

如果我重新安排订单,我会调用存储过程,它总是第二个错误。有没有办法,idk,重置调用之间的光标位置?我的元素有点偏离。

7 个答案:

答案 0 :(得分:4)

打开数据库的两个句柄。 ODBC可能会将光标保持在句柄中。

答案 1 :(得分:2)

我也发现了确切的问题。显然,这对于免费的ODBC驱动程序很常见。这是我早上头痛的尝试将项目从MySQL迁移到ODBC SQL Server。我终于找到了摆脱这个的东西。

出现此错误,因为前一个结果集中仍存在活动光标。我可以在不使用断开连接/重新连接方法的情况下通过确保在发出新记录集之前读取整个第一个记录集(即使只使用其中的一部分)来摆脱此错误。注意:我正在使用PHP。

给我一个错误:

$ sql =“SELECT COUNT(无论如何),无论是什么来自”; $ countResult = odbc_exec($ db,$ sql);
$ countMenuHeader = odbc_fetch_array($ countResult);
extract($ countMenuHeader);
$ countRecords = $ NumMenuHeader;

$ sql =“无论如何,选择任何东西”; $ result = odbc_exec($ db,$ sql);
$ MenuHeader = odbc_fetch_array($ result);

清除错误:

$ sql =“SELECT COUNT(无论如何),无论是什么来自”; $ countResult = odbc_exec($ db,$ sql);

while($ countMenuHeader = odbc_fetch_array($ countResult))
{
extract($ countMenuHeader);
$ countRecords = $ NumMenuHeader;
}

$ sql =“无论如何,选择任何东西”; $ result = odbc_exec($ db,$ sql);
$ MenuHeader = odbc_fetch_array($ result);

简而言之,请确保在移至数据集之前完全读取或获取数据集 下一个陈述。

答案 2 :(得分:1)

我遇到了同样的问题,但是两个查询之间的odbc_free_result($result)为我完成了这项工作。

Documentation

  

bool odbc_free_result ( resource $result_id )

     

与结果相关的免费资源。

     如果你担心的话,只需要打电话给{p> odbc_free_result()   在脚本运行时使用太多内存。所有结果记忆   脚本完成后将自动释放。

     

注意:   如果禁用自动提交(请参阅odbc_autocommit()),则之前请致电odbc_free_result()   提交后,所有待处理的事务都将回滚。

答案 3 :(得分:1)

尝试使用SQL Server获得无效光标状态的人的方法:

SET NOCOUNT ON;

在存储过程或SQL脚本的顶部。 在这里找到:https://social.msdn.microsoft.com/Forums/en-US/f872382a-b226-4186-83c7-0d0fcadcd3eb/invalid-cursor-state?forum=sqldataaccess 我有这个问题,只是在SQL Server 2017中运行了一些非常普通的SQL

答案 4 :(得分:0)

尝试使用不同的游标$ result1和$ result2访问结果。

答案 5 :(得分:0)

只是为了澄清调用finish()意味着您只是完成了当前查询及其结果,现在您可以再次安全地调用execute()。无需先再次调用prepare()。

我在AIX上使用ODBC驱动程序到DB2 SQL数据库时遇到了这个问题。我认为AIX有一个旧的ODBC驱动程序可能是因为Linux上的东西很好。

无论如何,我做了一个SQL查询,在for循环中反复返回一行,如下所示,得到24000错误。

my $sth = $dbh->prepare( $query ) or die "dying";

foreach my $i (@blah)
{
    $sth->execute($fred, $i) or die "dying";

    my $hash_ref = $sth->fetchrow_hashref("NAME_uc"); # only a single row exists

    ...

    $sth->finish(); # MUST do this
} 

我的结论是我必须调用$ sth-> finish()以便我可以安全地再次调用$ sth-> execute(),否则我可能会收到“无效的游标状态.SQLSTATE = 24000”错误消息

这是因为我们必须确保在移动到下一个语句之前完全读取或获取所有数据集。$ sth-> finish()向DBI表明您已完成 声明句柄。然后可以将其重用于执行execute()

的调用

我还发现我可以将fetch放在while循环中,即使只返回了一行而是查询。似乎尝试获取下一个不存在的行也使得sth可以执行。

my $sth = $dbh->prepare( $query ) or die "dying";

for
{ 
    $sth->execute($fred, $i) or die "dying";

    while (my $hash_ref = $sth->fetchrow_hashref("NAME_uc"))
    {
         ...
    }    
}

两种解决方案都适合我。 :)

答案 6 :(得分:0)

使用PHP中的unixODBC和freeTDS打开嵌套查询

如果你可以修改你的odbc.ini,使用相同的连接信息创建另一个配置部分,但使用另一个部分名称:

[DATASOURCE1]
Description = "Data Connection 1"
Driver = FreeTDS
Server = <your server>
Port = 1433
Database = <your db>

[DATASOURCE1A]
Description = "Data Connection 2"
Driver = FreeTDS	
Server = <your server>
Port = 1433
Database = <your db>

然后在您的代码中创建两个句柄,每个句柄对应一个数据源描述:

$dbhandle = odbc_connect('DATASOURCE1', 'user', 'password');
$dbhandle1 = odbc_connect('DATASOURCE1A', 'user', 'password');

然后您可以在嵌套查询中使用句柄:

$dbresult = odbc_exec($dbhandle, "SELECT <some sql>");
while($row = odbc_fetch_array($dbresult)) {

	$dbresult1 = odbc_exec($dbhandle1, "<some different sql>");

	while($row1 = odbc_fetch_array($dbresult1)) {
		
		#do stuff with nested query data like $row['name'] and $row1['time']
	}
}

您可以更深入地嵌套,但您必须为每个级别创建odbc.ini条目。 它并不漂亮,但在有多个游标可用之前它适用于我。

相关问题