CSV导入MySQL

时间:2012-12-10 19:56:28

标签: perl

您好我在尝试运行以下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);
}

2 个答案:

答案 0 :(得分: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传递给命令行上的脚本,假设这是正确的文件。

此外,在查询字符串中,不应插入变量,应使用占位符,如documentation for 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);

答案 1 :(得分: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;