DBエラー発生時の一括処理
本当は私PHP畑の人間なんですが、、
最近全然違う言語とかインフラやってます。
「悲しいけどこれって仕事なのよね。」
「坊やだからさ」
うるさいこのガ○ダム!
独り言はこれくらいにして、今回の例は「DBエラー発生時の一括処理を書いてみた」
です。
実際、今回が初めてperlを触っているので、
perlの罠にはまりっぱなしですが、ちょっと作ってみたので覚書。
※ソースの動確してません。間違いがあったらお知らせください。
前提条件
・必要なモジュールはすでにCPANから落としてきていること
CPAN -> http://search.cpan.org/
use DBI;
#require
require 'pram.pl';# 変数定義
my $dbh;#DBconnect
$dbh = DBI->connect("dbi:Oracle:host=$HOST;sid=$SID", $USER, $PWD,
{RaiseError => 1, PrintError => 0, AutoCommit => 0 });
if($dbh == undef ) {
print "コネクトに失敗しました。処理を終了します。";
exit;
}#主制御
&main();#メインメソッド
sub main{
#SQL作成
my $sql = "SELECT * FROM TESTTBL";
#エラーヘッダー作成
$sqlMsg = "【SELECT ERROR】";
#実行メソッドに送る
&query($sql,$sqlMsg);#SQL作成
my $sql2 = "INSERT INTO TESTTBL VALUES('hoge','hogehoge')";
#エラーヘッダー作成
$sql2msg = "【INSERT ERROR】";
#実行メソッドに送る
&query($sql2,$sql2msg);
}#実行メソッド
sub query{#引数取得
$sql = $_[0];
$msg = $_[1];eval{
$nres =$dbh->prepare($sql);
#実行
$nres->execute();#ここまできたらコミット
$dbh->commit;
};
if ( $@ ){#ロールバック
$dbh->rollback;#エラー出力
print $msg.$dbh->errstr;
#処理を続行したい場合は外す
exit;
}
}
抜粋して書くとさっぱりしますね。
軽く説明
require 'pram.pl';
ここにDB情報が入ってます。
$dbh = DBI->connect("dbi:Oracle:host=$HOST;sid=$SID", $USER, $PWD,
{RaiseError => 1, PrintError => 0, AutoCommit => 0 });
DBのコネクトとともに、AutoCommitをOFFにします。0にすることでコミットとロールバックのタイミングを
こちらで指定してやる必要があります。
また、PrintErrorも0にしたのは重複でエラーが出てしまうので、それを防ぐために0にしています。
コネクトに失敗したらそこで処理終了。
#クエリ作成
my $sql = "SELECT * FROM TESTTBL";
ここでprepareしてしまうと、
もしもエラー発生時の対処が必要な場合、
SQLごとにその処理を書かなくてならないので、
ここでは文字列として変数に渡します。
#エラーヘッダー作成
$sqlMsg = "【SELECT ERROR】";
#実行メソッドに送る
&query($sql,$sqlMsg);
ヘッダーを作成して、SQLと一緒にメソッドへ送る。
eval{
$nres =$dbh->prepare($sql);
#実行
$nres->execute();#ここまできたらコミット
$dbh->commit;
};
引数を取得したら、ここでprepare
evalで囲むことによってtry~cachの役割を果たしくれます。
エラーが発生しなかった場合はそのままコミット。
if ( $@ ){
#ロールバック
$dbh->rollback;#エラー出力
print $msg.$dbh->errstr;exit;
}
エラーが発生した場合はこちらに流れてくるので、
ロールバック処理。
先ほど作成したエラーヘッダーとあわせて、ORACLEの
エラーを出力。
******************************
こんな感じにすれば毎回prepareした時にエラー出力処理を書かなくてもいいはずです。
多少ソースが綺麗に見えるかな?
それと、今回は書いていませんが、
ロールバック>エラーをログに出力>処理続行
なんて処理を書きたい場合もあるでしょう。
そんな時はif( $@ )内にあるexitを外して、
エラー出力の場所に証跡ログを出力するメソッドを追加してやればOKです。
この記事を参考に実装した際の損害、障害は一切責任を負いかねます。
実装時は自己責任でお願いします。