2012-09-04 47 views
4

我使用开/打印执行用sqlplus SQL语句,就像这样:如何在使用open/print执行SQL语句时捕获退出代码?

open (PLSQL, "|sqlplus -s $db_url"); 
print PLSQL <<ENDSQL; 
... some SQL statements ... 
exit; 
ENDSQL 
close(PLSQL); 

我的问题是如何,如果它运行到一些错误捕获执行SQL语句的退出代码。我认为使用DBI应该更好,但我更喜欢解决上述问题。非常感谢!

回答

1

我还没有看到SQLPlus为SQL语句返回适当的退出代码,只有失败的连接或验证。

echo "SELECT * FROM NO_EXIST;" | sqlplus64 -S USER/[email protected]/MYAPP ; echo $? 
SELECT * FROM NO_EXIST 
      * 
ERROR at line 1: 
ORA-00942: table or view does not exist 


0 

我极力推荐的In-语言库,如果你能管理它。我不能,所以grep输出为ORA-\d\d\d\d\d\d作为失败的指示。

希望有所帮助。

+0

thx Sam!有没有办法使用system()? – Orunner

+0

系统(...)会将您的进程的STDIO提供给子进程。你想要的是类似ruby的popen3。你也可以使用Perl的Expect绑定。或者,第三个选项,您可以创建3个IO管道,然后fork,然后重新绑定子进程的STDIO以使用3个管道,然后使用exec sqlplus。父进程然后使用这些管道的另一端。 – Sam

+1

在SQL脚本的开头添加'WHENEVER SQLERROR EXIT FAILURE;'或'WHENEVER SQLERROR EXIT SQL.SQLCODE;'会导致错误返回非0值。 'WHENEVER SQLERROR EXIT SQL.SQLCODE;'并不像看起来那么有用,因为它只包含实际错误代码的最低8位。 –

1

正如您所说,使用DBI模块比使用sqlplus进行数据库操作要好得多。该实用程序仅作为命令行的便利,不适用于任何主要的数据库操作,并且使用该模块可以更好地控制处理可能出现的任何错误,这似乎是您的问题的要点

Perl本身不允许连接进程的STDIN和STDOUT。为此,您需要使用CPAN的IPC::Open2模块。阅读关于在Bidirectional Communication with Another Process

+0

虽然open2没有内置函数,但IPC :: Open2并不需要从CPAN下载,它已经成为一个适合年龄的核心模块。 –

5

close()问题应该告诉你你想知道什么呢:

如果文件句柄从开启,关闭返回false一个管道来了,如果所涉及的其他系统调用的一个失败,或者如果它的程序以非零状态退出。如果唯一的问题是程序退出非零,$!将被设置为0。关闭管道也等待在管道上执行的进程退出 - 如果希望事后查看管道的输出,并隐式地将该命令的退出状态值放入$中?和$ {^ CHILD_ERROR_NATIVE}。

要点是close()将返回false的任何错误,$!将只有一个系统调用了一个错误,$?将被设置为退出状态设定。详情请参阅Error Variables in perlvar

+0

我需要在测试中将'$?'除以256。例如: 'perl -e'open(F,qq(sh -c“exit 1”|));关闭F;打印$?/ 256'' 打印1而 'perl -e'open(F,qq(sh -c“exit 7”|));关闭F;打印$?/ 256'' 打印7. –

+2

@AdamKatz在错误变量文档中,我链接了它,列出了如何查找'$?':“的各种内容:”因此,子进程的退出值真的是'($?>> 8)'和'$?&127'给出哪个信号(如果有的话),进程死了,'$?&128'报告是否有核心转储。“比特移位('>>')通常比划分更受欢迎,因为它比平常更快,并且总是会产生整数结果。 –

相关问题