2013-02-01 57 views
1

我有一个使用PL/SQL代码生成的动态SQL SELECT语句。如何在Perl DBI中获取动态SQL输出?

declare 
    sql_query clob; 
begin 
    sql_query := 'select * from ...........'; 
    execute immediate sql_query; 
end; 

我想要检索上述动态生成SELECT语句的输出转换成在Perl的阵列。我已经尝试在Perl是,

$sql = "declare 
    sql_query clob; 
    begin 
    sql_query := 'select * from ...........'; 
    execute immediate sql_query; 
    end;"; 

$sql_prep = $dbh->prepare($sql) or die "Cannot prepare."; 
$sql_prep->execute() or die "Cannot execute."; 

while (@row = $sql_prep->fetchrow_array()) { 
    print "@row\n"; 
} 

而我得到的错误是,

DBD::Oracle::st fetchrow_array failed: ERROR no statement executing (perhaps you need to call execute first) [for Statement "declare 
........ 
........ 
"] at ./script.pl line 60. 

我为PL/SQL新手,我不知道如果我有遵循正确的道路。有人可以请教我这个吗?

在此先感谢!

- Shaakunthala

+1

你为什么不在你的代码的Perl端构造动态SQL?它比一个丑陋的PL/SQL块更容易 –

+1

同意w/Miguell Prz ...在您的Perl代码中构建一个SELECT语句,然后执行()它。 SQL是否必须在PL/SQL中动态创建?如果是这样,那么你可以为SQL字符串绑定一个输入/输出变量,或者绑定一个ORA_RSET in/out变量来有效地返回一个语句句柄......查看DBD :: Oracle文档。 – runrig

回答

2

我不是特别熟悉PL/SQL,但我知道,你的SQL字符串看起来极像是多条语句,并作为安全预防措施,DBI将只执行一个声明一次。也许它只是运行declare而忽略其余部分。

是否有一个原因,你这样做是这种方式,而不是仅仅直接运行select? (同样的代码,除了与$sql设置为select * from ..........的周围没有额外的比特)。如果你想在更普遍的情况下,动态声明一个存储过程,你可能(也可能不会)使用DBI的do方法,而不是有更好的运气的prepare/execute来声明它,然后将它作为单独的步骤与execute一起运行。

+0

感谢您的回复。我不得不动态生成SQL查询,这将不时地产生不同数量的列。我会试一试'do'方法。 – Shaakunthala

+1

PL/SQL块中允许有多个语句。但到目前为止,PL/SQL在这里似乎没有必要,似乎OP应该只是执行SELECT语句,而不是PL/SQL。 – runrig

3

在发帖时,如果你表现出多一点的代码,它可以帮助未来 - 在这种情况下,完整的SQL可能有助于至少确定哪些行抛出错误(也称线60,而你没有有一条线60)。

你不能做你想做的事情。您可以动态地在Perl中创建SQL,并将其传递到准备,执行,然后fetchXXX(或使用select *方法之一),或者如果您需要在PL/SQL中动态创建SQL,则需要创建一个过程它返回一个SYS_REFCURSOR(例子见DBD :: Oracle)。

正如前面的海报中提到的do方法,似乎你误解了他,你应该认识到do和prepare/execute之间的区别。 do不会返回一个语句句柄(它会返回一个表示操作成功或受影响行数的状态)。因此,您无法使用do获取任何行,因为没有用于调用fetch的语句句柄。 do方法通常用于DDL或插入/更新/删除语句。

prepare方法返回一个语句句柄,以便您可以从中读取行如果SQL是select语句。

如果我误解了你正在尝试做的事情,请告诉我,我可以举几个例子。

+0

对不起,没有发布整个代码。它太长了。基本上我想表明,我正在动态生成一个'SELECT'并使用DB上的'EXECUTE IMMEDIATE'来执行它。 我会根据您的建议寻找一些'SYS_REFCURSOR'示例。另外,使用Perl动态生成'SELECT'是一个好主意,对于新手来说看起来很干净。 :) 谢谢! – Shaakunthala