1

配列 (特定の基準を満たす顧客の候補リスト) をループし、 system() を使用して外部コマンドを実行し、操作が完了したら各行内のフィールドを更新する Perl スクリプトを作成しました。

最初のレコード (つまり、外部コマンドの実行、顧客レコードの更新) で機能しますが、2 番目のレコードに到達すると、次のエラーが表示されます。

DBD::mysql::st fetchrow_array が失敗しました: customer_update.pl で execute() なしで fetch()

グーグルで $sth->finish(); を追加しました。コマンドですが、それを含めても含めなくても(示されているようにループ内にあるか、または直後に)、同じエラーが発生します。

ここで私が間違っていることについて、誰かが私に光を当てることができますか?

ここに抜粋があります:

# PERL MYSQL CONNECT()
$dbh = DBI->connect('dbi:mysql:signups', $user, $pw) 
or die "Connection Error: $DBI::errstr\n";

# DEFINE A MySQL QUERY
$myquery = "SELECT * FROM accounts WHERE field3 = false";
$sth = $dbh->prepare($myquery);

# EXECUTE THE QUERY
$sth->execute
or die "SQL Error: $DBI::errstr\n";

@records = $sth->rows;
print "Amount of new customers: @records\n\n";

while ( my ($field1, $field2, $field3) = $sth->fetchrow_array() ) {
    #execute external command via system();
    $update_customer_status = "UPDATE accounts SET field3=true WHERE id=$id";
    $sth = $dbh->prepare($update_customer_status);
    $sth->execute
    or die "SQL Error: $DBI::errstr\n";
    print "Customer record modified & MySQL updated accordingly\n\n";   
    $sth->finish();
}
4

3 に答える 3

4

変数を使用して SQL ステートメントを作成し、それを prepare() すると、準備の目的が無効になります。?の代わりにプレースホルダーを使用して SQL ステートメントを作成し$id、prepare() してから execute($id) する必要があります。そのままでは、SQL インジェクション攻撃に対して無防備なままになっています。

warningsまた、 andstrictプラグマを使用していないようです。これらの 2 行は、作成するすべてのプログラムの先頭にある必要があります。

use warnings;
use strict;

彼らは将来、あなたの心痛やフラストレーションを大幅に軽減してくれます。

于 2013-09-09T02:36:15.070 に答える
4

ループでは、フェッチ元のハンドルを上書きします。別の変数を使用してください。( に変更$sth = ...;my $sth = ...;ます。) ここまで来たらprepare、 をループの外に移動しましょう。

my $sth_get = $dbh->prepare("SELECT * FROM accounts WHERE field3 = false");
my $sth_upd = $dbh->prepare("UPDATE accounts SET field3=true WHERE id = ?");

$sth_get->execute();
while ( my ($field1, $field2, $field3) = $sth_get->fetchrow_array() ) {
    ...
    $sth_upd->execute($id);
}
于 2013-09-09T01:47:16.553 に答える