0

複数の .csv ファイルを mysql データベースにインポートしようとしています。以下のスクリプトは、csv データの最初の行のみをデータベースにインポートすることを除いて機能します。両方のテーブルには、1 つのデータ エントリが入力されています。

どんな助けでも大歓迎です。

ありがとうございました

#!/usr/bin/perl

use DBI;
use DBD::mysql;
use strict;
use warnings;

# MySQL CONFIG VARIABLES
my $host = "localhost";
my $user = "someuser";
my $pw = "somepassword";

my $database = "test";
my $dsn = "DBI:mysql:database=" . $database . ";host=" . $host;

 my $dbh = DBI->connect($dsn, $user, $pw)
   or die "Can't connect to the DB: $DBI::errstr\n";

 print "Connected to DB!\n";


# enter the file name that you want import

my $filename = "/home/jonathan/dep/csv/linux_datetime_test_4.26.13_.csv";

open FILE, "<", $filename or die $!;

$_ = <FILE>;
$_ = <FILE>;

while (<FILE>) {
   my @f = split(/,/,$_);

if (length($f[4]) < 10) {
            print "No Weight\n"; 
    }
    else {
           #insert the data into the db
           print "insert into datetime_stamp\n"; 
}
        my $sql = "INSERT INTO datetime_stamp (subject, date, time, weight)                       
VALUES('$f[1]', '$f[2]', '$f[3]', '$f[4]')";
    print "$sql\n";
        my $query = $dbh->do($sql);

        my $sql = "INSERT INTO subj_weight (subject, weight) VALUES('$f[1]', '$f[2]')";
        my $query = $dbh->do($sql);

close(FILE);
}
4

1 に答える 1

3

コメントされているように、最初のデータ エントリを読み取った後に入力ファイルを閉じるため、データベースに 1 つのレコードのみを入力します。

ただし、コードには考慮すべきいくつかの問題があります。

  • プログラムの実行時に診断を出力する場合はautoflush、ファイル ハンドルを設定する必要があります。STDOUTそうでなければ、perl は出力するテキストでバッファがいっぱいになるか、プログラムが終了するときにファイルハンドルが閉じられるまで、出力を出力しません。つまり、イベントがかなり後になるまで、コーディングしたメッセージが表示されない場合があります。

  • Text::CSVに依存するのではなく、CSV データを解析するために使用する必要があります。split

  • 変数を二重引用符で囲まれた文字列に補間できます。これにより、複数の連結演算子の使用が回避され、意図がより明確になります。

  • の 3 パラメーター形式を正しく使用し、それが成功したかどうかをテストして文字列を挿入するため、あなたopenはほぼ完璧です (珍しいことです) 。ただし、昔ながらのグローバル ファイル ハンドルの代わりに、レキシカル ファイル ハンドルも常に使用する必要があります。open$!die

  • 入力から読み取った行ではないchompため、最後のフィールドには末尾の改行があります。を使用Text::CSVすると、この必要がなくなります

  • 入力レコードから分割されたデータのインデックス 1 ~ 4 を使用します。Perl のインデックスはゼロから始まるため、最初のフィールドを削除していることを意味します。あれは正しいですか?

  • subject同様に、 andのように見えるフィールド 1 と 2 を and というフィールドに挿入しdateます。これが正しいとは考えにくいsubjectweight

  • SQL ステートメントを作成し、プレースホルダーを使用して、呼び出しprepareで実際のデータを提供する必要があります。execute

  • ファイルから読み取ったデータを診断しているようですが (「重量なし」)、とにかくデータをデータベースに挿入します。これは正しいかもしれないが、ありそうにない

これらの修正を含むバージョンのプログラムを次に示します。お役に立てば幸いです。

#!/usr/bin/perl

use strict;
use warnings;

use DBI;
use Text::CSV;
use IO::Handle;

STDOUT->autoflush;

# MySQL config variables
my $host = "localhost";
my $user = "someuser";
my $pw   = "somepassword";

my $database = "test";
my $dsn      = "DBI:mysql:database=$database;host=$host";

my $dbh = DBI->connect($dsn, $user, $pw)
    or die "Can't connect to the DB: $DBI::errstr\n";

print "Connected to DB!\n";

my $filename = "/home/jonathan/dep/csv/linux_datetime_test_4.26.13_.csv";

open my $fh, '<', $filename
    or die qq{Unable to open "$filename" for input: $!};

my $csv = Text::CSV->new;

$csv->getline($fh) for 1, 2;  # Drop header lines

my $insert_datetime_stamp = $dbh->prepare( 'INSERT INTO datetime_stamp (subject, date, time, weight) VALUES(?, ?, ?, ?)' );
my $insert_subj_weight = $dbh->prepare( 'INSERT INTO subj_weight (subject, weight) VALUES(?, ?)' );

while (my $row = $csv->getline($fh)) {

    if (length($row->[4]) < 10) {
        print qq{Invalid weight: "$row->[4]"\n};
    }
    else {
        #insert the data into the db
        print "insert into datetime_stamp\n";
        $insert_datetime_stamp->execute(@$row[1..4]);
        $insert_subj_weight->execute(@$row[1,4]);
    }
}
于 2013-04-26T20:07:18.647 に答える