【问题标题】:perl: executing stored procedure which uses selectperl:执行使用选择的存储过程
【发布时间】:2017-06-21 02:26:06
【问题描述】:

我在尝试通过 Perl 运行存储过程时遇到了一些错误。

以下语句在 sqlDeveloper 中运行良好并返回预期结果

EXEC alpha.beta.do_something()

正如预期的那样,这不会产生任何输出

Select alpha.beta.get_something(alpha.STRING_ARRAY('xyz')) from tableName

这会生成 DBA 人员提供给我们的输出。它在 DB 术语中具有这种格式:Output Type:Ref Cursor。光标有两列,ab

通过 Perl 运行时,运行第二条语句时出现错误。

这是我正在使用的 Perl 代码:

sub execute_procedure {
    my $dbh       = shift;
    my $procedure = shift;

    my $statement = "BEGIN $procedure; END;"
    my $sth;
    eval {$sth = $dbh->prepare($statement);};
    eval {$sth->execute();};

    if ($@) {
        print "failed";
    } else {
        print "passed";
    }
}

# Call 1
execute_procedure($dbh, "alpha.beta.do_something()")

# Call 2
execute_procedure($dbh, "Select alpha.beta.get_something(alpha.STRING_ARRAY('xyz')) from tableName")

调用 1 按预期工作,不会产生任何错误

调用 2 导致此错误

"选择 alpha.beta.get_something(alpha.STRING_ARRAY('xyz')) from tableName" 导致:PLS-00428:在这个中需要一个 INTO 子句 SELECT 语句(DBD 错误:错误可能在字符的 > 指示符附近 6 in 'BEGIN >Select alpha.beta.get_result(alpha.STRING_ARRAY('xyz')) 来自表名;结束;')

如果我从 execute_procedure 函数中的语句中删除 BEGIN 和 END,如下所示:

# my $statement = "BEGIN $procedure; END;";
my $statement = "$procedure";

那么它不会产生任何错误,但它会返回一个我不知道如何解析的结果

my $result = $sth->fetchrow_hashref;
print Dumper($result)

结果:

$VAR1 = {
  'alpha.beta.get_result(alpha.STRING_ARRAY(\'xyz\'))' => bless( {}, 'DBI::st' )
};

所以,我的问题是

  1. 执行使用 SELECT 语句的存储过程的正确方法是什么?应该使用BEGIN $procedure; END; 调用还是不使用BEGIN/END

  2. 如何从bless( {}, 'DBI::st' ) 获取实际数据?我尝试使用不同的获取选项:fetchrowfetchrow_hashref 等,但我无法从对象中获取实际数据

【问题讨论】:

  • 这看起来很眼熟。在过去的几天里,您是否已经问过同样的问题?
  • 是的,我昨天确实问过这个问题,但它缺少细节,人们要求我提供代码。我刚刚更新了另一个问题,很快就会删除它
  • 现在非常清楚了。看我的回答。
  • 请注意DBI 模块不允许您同时使用prepareexecute 多个语句。另外,$dbh->prepare('BEGIN') 是否成功取决于数据库驱动程序,创建事务的规范方法是在执行事务之前设置$dbh->{AutoCommit} = 0,然后相应地设置$dbh->commit$dbh->rollbackAutoCommit 默认启用,如果您将其设置为 false 值,则您请求的每个数据库操作都将被记录,等待执行或丢弃。

标签: oracle perl stored-procedures dbi


【解决方案1】:
$VAR1 = { 'alpha.beta.get_result(alpha.STRING_ARRAY(\'xyz\'))' => bless( {}, 'DBI::st' ) };

这里的值为a DBI statement handle。当您执行my $sth = $dbh->prepare(...) 时,您会得到同样的结果。它可能已经执行过了,所以你可以调用它上面的任何 fetch 方法。

my $result = $sth->fetchrow_hashref;
while (
    my $res = $result->{'alpha.beta.get_result(alpha.STRING_ARRAY(\'xyz\'))'}
        ->fetchrow_hashref
) {
    # ...
}

但这看起来很可怕,而且你可能不知道键是什么。因此,您可能只想遍历所有这些。

my $result = $sth->fetchrow_hashref;
foreach my $key ( keys %${ $result } ) {
    print "Processing results of $key\n";
    while ( my $res = $result->{$key}->fetchrow_hashref ) {
        # do things with the $res

    }
}

你只需要想出一个处理结果的好方法。如果哈希 ref 中只有一个键,上述循环也可以工作,因此您无论如何都可以使用它并希望始终只有一个。

【讨论】:

  • 行得通,谢谢!所以只是为了弄清楚问题(1),对于返回某些东西的存储过程,像“BEGIN $procedure; END;”一样运行它们;不是个好主意吗?
  • @comatose 我不知道。我以前没用过那种语法。
猜你喜欢
  • 2019-02-01
  • 2013-05-14
  • 1970-01-01
  • 2018-03-12
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 2016-07-03
  • 2013-01-08
相关资源
最近更新 更多