2

Perl には 3 つの異なる配列 (A、B、C) があります。今、私は mysql に 3 つのフィールドを持つテーブルを持っています。

私がやろうとしているのは、配列 A のすべての内容を mysql テーブルの最初のフィールドに取得し、配列 B の内容を 2 番目のフィールドに取得することです。foreach ループを使用してこれを実行しようとしましたが、最初の配列では正常に機能しますが、2 番目と 3 番目の配列には何も挿入されません。

コードは次のように使用されます。

foreach my $a (@a) {

    my $sql = "insert into es(a) VALUES(\"$a\")";
    my $sth = $dbh->prepare($sql);
    $sth->execute or die "SQL Error: $DBI::errstr\n";
}


foreach my $b (@b) {

    my $sql = "insert into es(b) VALUES(\"$b\")";
    my $sth = $dbh->prepare($sql);
    $sth->execute or die "SQL Error: $DBI::errstr\n";

}

3 番目についても同様です。テーブルの列 a は正しく入力されますが、テーブルの列 b と c にはデータがありません。私は何を間違っていますか。

4

1 に答える 1

6

あなたはリレーショナル データベースについてあまりよく知らないと思います。あなたがしたことは次のとおりです。

  1. 繰り返す@a
  2. の各項目について新しいステートメントを準備する@a
  3. a値のみを含む挿入ごとに 1 行を追加します。つまり:
    • の各アイテムのデータセットを作成します@a
    • bcNULLです。

これで、 for@b@c同様に実行できます。それはあまり効率的ではありません。

DBIは、ここであなたを助けるように設計されています。次の規則 (ガイドライン) を考慮する必要があります。

  • 常に DBI のquoteメソッドまたはより優れたプレースホルダーを使用してください。これにより、自分で引用符を追加する手間が省けます。
  • ループと複数INSERTの やが存在する場合、クエリUPDATEは常にprepareループの外にあり、ループ内にあるだけexecuteです。

それでは、あなたの問題を見てみましょう。@a@bおよび@cすべてが同じ数のアイテムを持っていると仮定し、 およびのインデックスごとに 1 行@a@b@cが必要です。したがって、このデータがある場合:

my @a = (1, 2, 3);
my @b = qw(foo bar baz)
my @c = (999, 998, 997);

私の賭けは、データベースで次のようにしたいということです:

a b   c
1 foo 999
2 bar 998
3 baz 997

したがって、3 つINSERTの s を 1 つのステートメントに結合する必要があります。これは、それらすべてを一度に繰り返すことで実行できます。List::MoreUtilseach_arrayの関数を使用して、反復を処理できます。また、上記のガイドラインをコードに追加します。

use List::MoreUtils qw(each_array);
my $dbh = DBI->connect(); # connect to db here

# prepare the INSERT statement once
my $sth_insert = $dbh->prepare('INSERT INTO es SET a=?, b=?, c=?')
  or die $dbh->errstr;

# create the array iterator
my $ea = each_array(@a, @b, @c);
# iterate over all three arrays step by step
while ( my ($val_a, $val_b, $val_c) = $ea->() ) {
  $sth_insert->execute($val_a, $val_b, $val_c) or die $dbh->errstr;
}
于 2012-09-21T10:47:53.267 に答える