2012-09-04 72 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'報告是否有核心轉儲。「比特移位('>>')通常比劃分更受歡迎,因爲它比平常更快,並且總是會產生整數結果。 –

相關問題