我使用開/打印執行用sqlplus SQL語句,就像這樣:如何在使用open/print執行SQL語句時捕獲退出代碼?
open (PLSQL, "|sqlplus -s $db_url");
print PLSQL <<ENDSQL;
... some SQL statements ...
exit;
ENDSQL
close(PLSQL);
我的問題是如何,如果它運行到一些錯誤捕獲執行SQL語句的退出代碼。我認爲使用DBI應該更好,但我更喜歡解決上述問題。非常感謝!
我使用開/打印執行用sqlplus SQL語句,就像這樣:如何在使用open/print執行SQL語句時捕獲退出代碼?
open (PLSQL, "|sqlplus -s $db_url");
print PLSQL <<ENDSQL;
... some SQL statements ...
exit;
ENDSQL
close(PLSQL);
我的問題是如何,如果它運行到一些錯誤捕獲執行SQL語句的退出代碼。我認爲使用DBI應該更好,但我更喜歡解決上述問題。非常感謝!
我還沒有看到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
作爲失敗的指示。
希望有所幫助。
正如您所說,使用DBI模塊比使用sqlplus
進行數據庫操作要好得多。該實用程序僅作爲命令行的便利,不適用於任何主要的數據庫操作,並且使用該模塊可以更好地控制處理可能出現的任何錯誤,這似乎是您的問題的要點
Perl本身不允許連接進程的STDIN和STDOUT。爲此,您需要使用CPAN的IPC::Open2
模塊。閱讀關於在Bidirectional Communication with Another Process
雖然open2沒有內置函數,但IPC :: Open2並不需要從CPAN下載,它已經成爲一個適合年齡的核心模塊。 –
close()
問題應該告訴你你想知道什麼呢:
如果文件句柄從開啓,關閉返回false一個管道來了,如果所涉及的其他系統調用的一個失敗,或者如果它的程序以非零狀態退出。如果唯一的問題是程序退出非零,$!將被設置爲0。關閉管道也等待在管道上執行的進程退出 - 如果希望事後查看管道的輸出,並隱式地將該命令的退出狀態值放入$中?和$ {^ CHILD_ERROR_NATIVE}。
要點是close()
將返回false的任何錯誤,$!
將只有一個系統調用了一個錯誤,$?
將被設置爲退出狀態設定。詳情請參閱Error Variables in perlvar。
我需要在測試中將'$?'除以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. –
@AdamKatz在錯誤變量文檔中,我鏈接了它,列出瞭如何查找'$?':「的各種內容:」因此,子進程的退出值真的是'($?>> 8)'和'$?&127'給出哪個信號(如果有的話),進程死了,'$?&128'報告是否有核心轉儲。「比特移位('>>')通常比劃分更受歡迎,因爲它比平常更快,並且總是會產生整數結果。 –
thx Sam!有沒有辦法使用system()? – Orunner
系統(...)會將您的進程的STDIO提供給子進程。你想要的是類似ruby的popen3。你也可以使用Perl的Expect綁定。或者,第三個選項,您可以創建3個IO管道,然後fork,然後重新綁定子進程的STDIO以使用3個管道,然後使用exec sqlplus。父進程然後使用這些管道的另一端。 – Sam
在SQL腳本的開頭添加'WHENEVER SQLERROR EXIT FAILURE;'或'WHENEVER SQLERROR EXIT SQL.SQLCODE;'會導致錯誤返回非0值。 'WHENEVER SQLERROR EXIT SQL.SQLCODE;'並不像看起來那麼有用,因爲它只包含實際錯誤代碼的最低8位。 –