質問

この質問は池上氏の次のコメントを参照しています。

[...] But if you're going to put an eval around every statement, just use RaiseError => 0. [...]

この中で .

設定すると何が得られますか RaiseError0 そのような状況では?

#!/usr/bin/env perl
use warnings;
use 5.10.1;
use DBI;

my $db = 'my_test_sqlite_db.sqlite';
open my $fh, '>', $db or die $!;
close $fh or die $!;

my ( $dbh, $sth );
eval {
    $dbh = DBI->connect( "DBI:SQLite:dbname=$db", "", "", {} );
};
if ( $@ ) { print $@ };

my $table = 'my_sqlite_table';

say   "RaiseError = 1";
say   "PrintError = 0";
$dbh->{RaiseError} = 1;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 1";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 1;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 0";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

出力:

RaiseError = 1
PrintError = 0
ERROR: DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 23.

RaiseError = 0
PrintError = 1
DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 33.
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 34.

RaiseError = 0
PrintError = 0
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 44.
役に立ちましたか?

解決

何らかの理由で失敗した場合、ほとんどの $dbh メソッドは次のいずれかを実行します。

  • (もし RaiseError オプションは 0 に設定されています) return undef
  • (もし RaiseError オプションが 1 に設定されている場合) エラー理由が終了メッセージとして表示され、スクリプトを直ちに終了します (「die」)。

ここで重要なのは、エラーをどのように処理するかはユーザー次第であるということです。必要に応じて、たとえば、これらを無視することもできます (以下は明らかに機能します) RaiseError に設定 0 のみ):

for my $db ( ... ) {
    my $dbh = get_database_handle( $db )
       or next;
    ...
}

このスニペット (質問で言及した @ikegami の回答からコピーしたもの) では、DB 接続の設定のリストをループします。何らかのつながりがあなたに与えてくれるなら undef, 、別のものを選択するだけで、エラーが発生しても何もしません。

ただし、通常は、エラーが発生したときに単に「次へ」という以上のことを行う必要がありますが、その場合も 2 つの選択肢があります。どちらかをチェックしてください それぞれ $dbh- 関連のステートメントには次のようなものがあります:

$sth = $dbh->prepare('some_params') 
  or process_db_error('In prepare');
...
$res = $sth->execute('another_set_of_params') 
  or process_db_error('In execute');
...
$res->doAnythingElse('something completely different') 
  or process_db_error('In something completely different');

(として or 部分は、対応する「左側の部分」が次のように評価された場合にのみ実行されます。 false ブール値のコンテキストで).

...または、これらすべてを Perlish の「try-catch」ブロックにラップするだけです。

if (!eval {    
   $sth = $dbh->prepare('some_params');
   ...
   $res = $sth->execute('another_set_of_params');
   ...
   $res->doSomethingElse('something completely different') 
   ...
   1  # No exception
}) {
   process_db_error($@);
}

何を選択するかはあなた次第です:これは、「return ステートメントのエラー」 (実際のエラーをフェッチするには $dbh オブジェクトに問い合わせる必要があることを除く) と例外の間の一般的な決定です。

しかし、肝心なのは、これだけを書くことはできないということです。

$sth = $dbh->do_something('that_can_result_in_error');
$sth->do_something('else');

...設定した場合 RaiseError0. 。この場合、スクリプトは死ぬことはありません。 $sth が割り当てられます undef, 、そして、「派生」エラーが発生します(メソッドを呼び出すことができないため) undef).

そして、それはまさに、元の質問のコードの最後の部分で起こったことです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top