6

我需要在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]游标状态无效,SQLExecDirect 中的 SQL 状态 24000

如果我重新安排我调用存储过程的顺序,它总是第二个错误。有没有办法,idk,在调用之间重置光标位置?有点不合我意。

4

7 回答 7

10

尝试让人们使用 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在 SQL Server 2017 中

于 2019-01-16T04:52:05.417 回答
4

打开数据库的两个句柄。ODBC 可能会在句柄中维护光标。

于 2009-11-18T00:01:13.877 回答
2

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

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

给我一个错误:

$sql="SELECT COUNT(whatever) as whatever FROM whatever";<br />
$countResult = odbc_exec($db, $sql);<br />
$countMenuHeader = odbc_fetch_array($countResult);<br />
extract ($countMenuHeader);<br />
$countRecords = $NumMenuHeader;<br />

$sql="SELECT whatever as whatever FROM whatever";<br />
$result = odbc_exec($db, $sql);<br />
$MenuHeader = odbc_fetch_array($result);<br />

清除错误:

 $sql="SELECT COUNT(whatever) as whatever FROM whatever";<br />
 $countResult = odbc_exec($db, $sql);<br />

 while($countMenuHeader = odbc_fetch_array($countResult))<br />
 {<br />&nbsp;&nbsp;
 extract ($countMenuHeader);<br />&nbsp;&nbsp;
 $countRecords = $NumMenuHeader;<br />}

 $sql="SELECT whatever as whatever FROM whatever";<br />
 $result = odbc_exec($db, $sql);<br />
 $MenuHeader = odbc_fetch_array($result);<br />

简而言之,请确保在移动到下一条语句之前完全读取或获取数据集。

于 2011-05-24T15:28:20.697 回答
2

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

文档

bool odbc_free_result ( resource $result_id )

与结果相关的免费资源。

odbc_free_result()仅当您担心在脚本运行时使用太多内存时才需要调用。脚本完成后,所有结果内存将自动释放。

注意:如果禁用自动提交(参见 参考资料odbc_autocommit())并且您odbc_free_result()在提交之前调用,所有挂起的事务都会回滚。

于 2014-03-31T08:40:53.767 回答
0

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

于 2009-11-17T23:16:32.733 回答
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(),否则我会收到“Invalid cursor state.SQLSTATE=24000”错误消息。

这是因为我们必须确保在移动到下一条语句之前完全读取或获取所有数据集。$sth->finish() 向 DBI 指示您已完成语句句柄。然后可以重用它来调用 execute()

我还发现我可以将 fetch 放在一个 while 循环中,即使只返回了一行但查询。似乎试图获取下一个不存在的行也使某事可以重新执行。

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"))
    {
         ...
    }    
}

两种解决方案都对我有用。:)

于 2014-10-24T10:32:44.330 回答
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 条目。它不是很漂亮,但它对我有用,直到有多个游标可用。

于 2015-04-17T17:40:01.767 回答