1

嗨,当我尝试运行以下 perl 脚本将 csv 文件导入现有的 mysql 数据库表时,我不断收到错误消息。每次我运行它时,我都会收到消息“在 /home/perl/dep_import_2.pl 第 10 行死亡。

任何帮助,将不胜感激

谢谢

#!/usr/bin/perl

use DBI;
use DBD::mysql;
use warnings "all";


if ($#ARGV != 0) {
   print "Usage: dep_import_2.pl filename\n";
     die;
}
$filename = $ARGV[0];


# MySQL CONFIG VARIABLES
$host = "localhost";
$user = "standard";
$pw = "standard";

$database = "data_track";
$dsn = "DBI:mysql:database=" . $database . ";host=" . $host;

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

print "Connected to DB!\n";

open FILE, "/home/dep/new_study_forms_2.csv", $filename or die $!;

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

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

    $sql = "INSERT INTO dep (date, subject, weight, size, time, hi_pre, hi_post, hi_afternoon, hi_test, actical_on, actical_off, saggital_1, saggital_2, crown_heel1, crown_heel2, crown_rump1, crown_rump2, scan, record_number, tap, sample, dye, left_chip, right_chip) VALUES('$f[0]', '$f[1]', '$f[2]', '$f[3]' '$f[4]', '$f[5]', '$f[6]', '$f[7]', '$f[8]', '$f[9]', '$f[10]', '$f[11]', '$f[12]', '$f[13]', '$f[14]', '$f[15]', '$f[16]', '$f[17]', '$f[18]', '$f[19]', '$f[20]', '$f[21]', '$f[22]', '$f[23]')";
    print "$sql\n";
    my $query = $dbh->do($sql);
}
4

2 回答 2

4

您的代码存在一些问题。首先,也是最重要的,你没有使用

use strict;
use warnings;

这很糟糕,因为没有它们,您将无法获得有关代码中错误的信息。

正如其他人指出的那样,脚本死亡的原因$#ARGV是不是零。这意味着您向脚本传递的参数太少或太多。脚本的参数必须完全是一个,就像用法声明所说的那样。

但是,这并不能解决您的问题,因为您在下面的公开声明被搞砸了。我的猜测是你试图直接添加你的文件名。这一行:

open FILE, "/home/dep/new_study_forms_2.csv", $filename or die $!;

它可能会给你错误unknown open() mode ...。应该是

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

然后你/home/dep/new_study_forms_2.csv在命令行上传递给脚本,假设这是要使用的正确文件。

此外,在您的查询字符串中,您不应插入变量,而应使用占位符,如DBI 文档中所述。占位符将为您处理报价并避免任何数据损坏。为了使您的查询行更简单,您可以执行以下操作:

my $sth = $dbh->prepare(
    "INSERT INTO dep (date, subject, weight, size, time, hi_pre, hi_post, 
     hi_afternoon, hi_test, actical_on, actical_off, saggital_1, saggital_2,
     crown_heel1, crown_heel2, crown_rump1, crown_rump2, scan, record_number, 
     tap, sample, dye, left_chip, right_chip) 
     VALUES(" . join(",", ("?") x @f) . ")");
$sth->execute(@f);
于 2012-12-10T20:32:38.720 回答
3

这是一个使用Text::CSV正确解析 CSV 的脚本。它假定第一行包含列名,然后分批加载 CSV,每 100 次插入后提交。每个参数(用户、密码、数据库)都可以通过命令行选项进行配置。用法是内嵌的 POD 文档。

#!/usr/bin/env perl
use strict;
use warnings qw(all);

use DBI;
use Getopt::Long;
use Pod::Usage;
use Text::CSV_XS;

=pod

=head1 SYNOPSIS

    dep_import_2.pl --filename=file.csv --host=localhost --user=standard --pw=standard --database=data_track

=head1 DESCRIPTION

Loads a CSV file into the specified MySQL database.

=cut

my $host = 'localhost';
my $user = 'standard';
my $pw = 'standard';
my $database = 'data_track';
my $commit = 100;

GetOptions(
    'help'          => \my $help,
    'filename=s'    => \my $filename,
    'host=s'        => \$host,
    'user=s'        => \$user,
    'pw=s'          => \$pw,
    'database=s'    => \$database,
    'commit=i'      => \$commit,
) or pod2usage(q(-verbose) => 1);
pod2usage(q(-verbose) => 2) if $help;

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

my $csv = Text::CSV_XS->new
    or die "Text::CSV error: " . Text::CSV->error_diag;

open(my $fh, '<:utf8', $filename)
    or die "Can't open $filename: $!";

my @cols = @{$csv->getline($fh)};
$csv->column_names(\@cols);

my $query = "INSERT INTO dep (@{[ join ',', @cols ]}) VALUES (@{[ join ',', ('?') x (scalar @cols) ]})";
my $sth = $dbh->prepare($query);

my $i = 0;
while (my $row = $csv->getline_hr($fh)) {
    $sth->execute(@{$row}{@cols});
    $dbh->commit if ((++$i % $commit) == 0);
}

$dbh->commit;
$dbh->disconnect;

$csv->eof or $csv->error_diag;

close $fh;
于 2012-12-11T18:25:45.650 回答