为什么Perl的DBI抱怨“Fetch尝试未打开游标”?

时间:2009-05-07 13:42:41

标签: sql perl informix dbi dirtyread

这是我的剧本:

$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并显示表内容,它可以正常工作,但上面的代码不起作用。

4 个答案:

答案 0 :(得分:3)

selectrow_array方法适用于返回结果集的语句。 SET ISOLATION语句不是这样的语句 - 它会失败。

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

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

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

答案 1 :(得分:3)

您无法从正在执行的语句中获取结果:

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声明。

正如乔纳森所指出的,这可能不是最明显的错误,但一旦你理解了正在发生的事情,它确实有意义。

答案 2 :(得分:1)

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

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

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

答案 3 :(得分:1)

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;