5

DBI接続を使用するPerlスクリプトがあります。サブルーチンを使用してSQLスクリプトファイルを開いて読み取ります。私は1つのレコードのみを印刷していますが、さらに2つのレコード(合計3つのレコード)が必要です。すべてのレコードを取得するにはどうすればよいですか?

結果:

Alert:OUTBOUND_DATA:0

脚本:

my $dbh_oracle = DBI->connect(
          $CFG{oracle_dbi_connect},
          $CFG{db_user},
          $CFG{db_cred},
          {AutoCommit => 0,
           RaiseError => 0,
           PrintError => 0}) or die ("Cannot connect to the database: ".$DBI::errstr."\n");

my ($val1, $val2) = get_data();
print "Alert:$val1:$val2\n";

send_email("Alert:$val1:$val2");

sub get_data
{
  undef $/;
  open (my $QFH, "< /sql/summary.sql") or die "error can't open this file $!";
  my $sth= $dbh_oracle->prepare(<$QFH>) or
      die ("Cannot connect to the database: ".$DBI::errstr."\n");
  $sth->execute;
  close $QFH;
  my $row = $sth->fetchrow_hashref;
  $sth->finish;
  return @$row{'MYTABLE','FLAG'};
}

sub send_email {
    my $message = shift;
    open (MAIL, "|/usr/sbin/sendmail -t") or die "Can't open sendmail: $!";
    print MAIL "To: me\@test.com\n";
    print MAIL "From: Data\n";
    print MAIL "\n";
    print MAIL $message;
    close MAIL;
}
exit;

クエリの実行結果:(複数のレコード)

MYTABLE                  FLAG
----------------------- ----------
OUTBOUND_DATA         0
MSGS_BY_DIM                  0
INBOUND_DATA         0

3 rows selected.
4

4 に答える 4

9

ステートメントハンドルからデータを取得するには、さまざまな方法があります。最も一般的なものは非常に単純で、その使用法を以下に示します。

my @row_array = $sth->fetchrow_array;
my $array_ref = $sth->fetchrow_arrayref;
my $hash_ref  = $sth->fetchrow_hashref;

最初のfetchrow_arrayは、各行を順番に配列として返します。上記の選択から返されたデータを使用する例は次のとおりです。

while (my @row_array = $sth->fetchrow_array) {
    print $row_array[0], " is ", $row_array[1], " years old, and has a " , 
          $row_array[2], "\n";
}

2番目の例も同様ですが、配列ではなく配列参照を返します。

while (my $array_ref = $sth->fetchrow_arrayref) {
    print $array_ref->[0], " is ", $array_ref->[1], 
          " years old, and has a " , $array_ref->[2], "\n";
}

3番目の例であるfetchrow_hashrefは、多くの場合、最も読みやすいものです。

while (my $hash_ref = $sth->fetchrow_hashref) {
    print $hash_ref->{name}, " is ", $hash_ref->{age}, 
          " years old, and has a " , $hash_ref->{pet}, "\n";
}
于 2012-04-20T20:16:18.217 に答える
3

この行はループである必要があります。

my $row = $sth->fetchrow_hashref;

そのはず:

my @rows;
while ( my $row = $sth->fetchrow_hashref ) {
    push @rows, $row;
}
return @rows;

DBIにループを実行させたい場合は、selectall_arrayrefまたはselectall_hashrefを確認してください。

于 2012-04-20T20:06:08.310 に答える
3

また、スクリプト全体をどのように構成しているかによっても異なります。呼び出しget_data()では、値の1つのペアのみが返されます。少なくともいくつかのオプションがあります。すべてのデータを含むハッシュ(参照)を返してmainアセンブルさせるか、前述のループ構造を使用してサブルーチン内でメッセージ本文を作成し、単一のスカラー文字列のみを返します。

すべてのデータをハッシュ参照として返すために、get_dataサブルーチンは次のようになります( :fetchall_hashrefの代わりに使用していることに注意してくださいfetchrow_hashref

sub get_data
{
  undef $/;
  open (my $QFH, "< /sql/summary.sql") or die "error can't open this file $!";
  my $sth= $dbh_oracle->prepare(<$QFH>) or
      die ("Cannot connect to the database: ".$DBI::errstr."\n");
  $sth->execute;
  close $QFH;
  my $hash_ref = $sth->fetchall_hashref('MYTABLE');
  $sth->finish;
  return $hash_ref;
}

そして、それをから呼び出しmain、次のように出力を使用します。

my $hash_ref = get_data();
my $message = "";
foreach my $table (sort keys %$hash_ref) {
    $message .= join(":", "Alert", $table, $$hash_ref{$table}{'FLAG'}) . "\n";
}

これにより、次のもの$messageが含まれるようになります。

Alert:INBOUND_DATA:0
Alert:MSGS_BY_DIM:0
Alert:OUTBOUND_DATA:0

そして、あなたは丁寧にしたいかもしれません:

$dbh_oracle->disconnect;

終了する前に。

これにはいくつかの問題があります。たとえば、SQLが外部スクリプトに隠されていますが、キー(MYTABLE、クエリで一意であると推測されます)と値(FLAG)をハードコーディングすることにしました。スクリプト。これについては、後で拡張するときに制限されます。

于 2012-04-20T21:34:17.993 に答える
2

メソッドは、fetchrow_文字通り一度に1行だけフェッチします。

一部の列のすべての行が必要な場合は、データ構造を非効率的にプッシュするか、状況に応じた呼び出しを使用できます。

selectcol_arrayref次のように使用したいと思います。

my $ary_ref = $dbh->selectcol_arrayref(
    "select id, name from table",
    { Columns=>[1,2] }
);

列インデックスは、元のテーブルではなく、結果セット内の列の位置を参照します。

返されたすべての行を処理するには、返された結果の使用方法も変更する必要があります。

また、あなたは持っています:

sub get_data
{
  undef $/;

SQLを含むファイルを丸呑みするからです。ただし、$/はグローバル変数です。local $/可能な限り最小のスコープで使用する必要があります。それで:

my $sql = do { local $/; <$fh> };
于 2012-04-20T22:44:05.257 に答える