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

发布于 2024-08-12 00:21:39 字数 603 浏览 3 评论 0原文

我需要在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

舞袖。长 2024-08-19 00:21:39

对于使用 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 时遇到了这个问题

Something to try for people getting invalid cursor state with SQL server:

SET NOCOUNT ON;

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

满地尘埃落定 2024-08-19 00:21:39

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

Open two handles to the database. ODBC probably maintains the cursor in the handle.

过气美图社 2024-08-19 00:21:39

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

文档

bool odbc_free_result(资源 $result_id)

与结果相关的免费资源。

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

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

I ran into the same problem, but odbc_free_result($result) between the 2 queries did the job for me.

Documentation:

bool odbc_free_result ( resource $result_id )

Free resources associated with a result.

odbc_free_result() only needs to be called if you are worried about
using too much memory while your script is running. All result memory
will automatically be freed when the script is finished.

Note:
If auto-commit is disabled (see odbc_autocommit()) and you call odbc_free_result() before
committing, all pending transactions are rolled back.

半仙 2024-08-19 00:21:39

我也发现了确切的问题。显然,这在免费 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 />  
 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 />

简而言之,请确保在移动到
下一个声明。

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:

$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 />

Cleared the error:

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

 while($countMenuHeader = odbc_fetch_array($countResult))<br />
 {<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 />

In short, make sure you completely read or fetch the data set before moving to the
next statement.

夜光 2024-08-19 00:21:39

使用 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 条目。
它并不漂亮,但它对我有用,直到有多个光标可用。

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:

[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>

Then in your code create two handles, one for each data source description:

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

Then you can use the handles in nested queries:

$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']
	}
}

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.

空宴 2024-08-19 00:21:39

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

Try accessing the results using different cursors, $result1 and $result2.

好久不见√ 2024-08-19 00:21:39

只是为了澄清,调用 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()的调用。

我还发现我可以将提取放入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"))
    {
         ...
    }    
}

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

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 $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
} 

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.

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

Both solutions worked for me. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文