为啥 Perl DBI 抱怨“在未打开的游标上尝试获取”?

Posted

技术标签:

【中文标题】为啥 Perl DBI 抱怨“在未打开的游标上尝试获取”?【英文标题】:Why does Perl's DBI complain about "Fetch attempted on unopen cursor"?为什么 Perl DBI 抱怨“在未打开的游标上尝试获取”? 【发布时间】:2009-05-07 13:42:40 【问题描述】:

这是我的脚本:

$db_handle=DBI->connect("$dbstr", "", "",
RaiseError => 0, AutoCommit => 0, PrintError => 1) 
|| die "Connect error: $DBI::errstr" ;
$result=$db_handle->selectrow_array("set isolation to dirty read");

注意:$dbstr 是一个有效的数据库名称。

我不是数据库程序员。我做错了什么导致 Perl 脚本失败:

DBD::Informix::db selectrow_array 失败:SQL:-400:在未打开的游标上尝试获取。

如果我编写一个简单的脚本来连接数据库$dbstr 并显示表格内容,它可以正常工作,但上面的代码不起作用。

【问题讨论】:

请注意,有文档记录的地方可以寻求对 DBD::Informix 的支持(这不是其中之一,但在创建 DBD::Informix 的最后一个版本时它并不存在) .请注意,更重要的是,有 LOT 的版本信息需要回答更复杂的问题,包括以下版本:Perl、DBI、DBD::Informix、ESQL/C(或CSDK)、IDS(或其他 Informix DBMS)、平台,有时甚至是编译器。这些要求在源文件中列出。甚至还提供了一个脚本来收集其中的大部分内容 - InformixTechSupport。 【参考方案1】:

selectrow_array 方法旨在与返回结果集的语句一起使用。 SET ISOLATION 语句不是这样的语句 - 它会失败。

错误 -400 是否是最好的错误有点值得商榷 - 有时我会看看是否可以做任何事情。但是,IIRC,selectrow_array 方法是由 DBI 而不是 DBD::Informix 提供的,因此 DBI 从较低级别的原语构建它。因此,这些原语无法提供更高级别函数可以提供的验证,因为它们也必须单独工作。

编写该代码的正确方法是:

$db_handle->do("set isolation mode to dirty read");

【讨论】:

【参考方案2】:

您正在执行的语句中没有结果可供您获取:

set isolation to dirty read

所以selectrow_array() 是错误的调用方法。请改用$dbh->do(...):

$db_handle->do('set isolation to dirty read');

下面是对 -400 错误的详细解释:

-400 在未打开的光标上尝试获取。

此 FETCH 语句命名一个从未打开过的游标或 被关闭。查看程序逻辑,并检查它是否会打开 光标在此点之前,而不是意外关闭它。除非光标 被声明为 WITH HOLD,它由 COMMIT WORK 自动关闭或 ROLLBACK WORK 语句。

正如 Jonathan 所指出的,这可能不是最明显的错误,但一旦您了解了发生的情况,它确实是有道理的。

【讨论】:

【参考方案3】:

请阅读DBD::Informix 的文档,尤其是“CONNECTING_TO_A_DATABASE”部分。连接到 Informix 数据库所需的最少代码似乎是:

$dbh = DBI->connect("dbi:Informix:$database");

因此,您必须提供的不仅仅是数据库的名称。

【讨论】:

问题说连接正常 - 因此他们提供的不仅仅是数据库名称。不过,DBD::Informix 文档的外部参考仍然有用。【参考方案4】:

set isolation to dirty read 不是查询,而是语句。只有查询进入selectrow_array。你需要do:

#!usr/bin/perl

use strict;
use warnings;

use DBI;

my $dbi = "dbi:Informix:dbname";

my $dbh = DBI->connect(
    $dbi,
    "",
    "",
    
        RaiseError => 1,
        AutoCommit => 0,
        PrintError => 1,
        ChopBlanks => 1,
    
) or die "Connect error: $DBI::errstr";

my $result = $dbh->do("set isolation to dirty read");

$dbh->disconnect;

【讨论】:

以上是关于为啥 Perl DBI 抱怨“在未打开的游标上尝试获取”?的主要内容,如果未能解决你的问题,请参考以下文章

当跟踪中的语句返回 1 时,为啥 perl DBI 返回 0 行

为啥 Perl 的 GD::Graph 抱怨“无效数据集”?

为啥回滚方法不能用于 DBI 句柄?

Linux中perl-DBI和DBI有啥区别?

在 Windows-7-x64 上使用 DBI Perl 和 MySql 的未定义 $DBI::errstr

Perl/DBI/FreeTDS/SQLAzure 一些插入被忽略