使用Perl从CSV到MySQL数据库

时间:2014-02-19 12:03:42

标签: mysql perl

我尝试将一些数据从CSV上传到MySQL数据库 - 但它无法正常工作

下面是我的代码

#!/usr/bin/perl -w
use DBI;
use strict;
use TEXT::CSV;
use warnings;

my $driver       = "mysql"; 
my $database     = "test";
my $host         = "localhost"
my $databaseport = "3306";
my $userid       = "root";
my $password     = "password";
my $csv          = "C:/Perl/scripts/table.csv";

my $dsn          = "dbi:mysql:dbname=$databasename;host=$dbhost;port=$dbport;";

open (CSV, "$csv") or die "Couldn't open csvfile: $!";
my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1})
or die "Could not connect to database! $DBI::errstr";
{ 
 local $/ = undef; 
  $dbh->do("INSERT INTO student (stud_id,stud_name,dept_id,stud_mark,stud_address) 

  values (?, ?, ?, ?, ?)", undef, <CSV>);
 }
 $dbh->disconnect;
close CSV;

2 个答案:

答案 0 :(得分:6)

这里有一些问题。我将列出那些首先会给你错误信息的内容。

  • 没有模块TEXT :: CSV。虽然有一个叫Text::CSV
  • 您在查询中使用了5个占位符,但是您通过菱形运算符<CSV>传递了csv文件的第一行。这将给出错误信息。

然后你的逻辑有问题。您正在将完整文件传递给DB(作为第一个参数)。那没有意义。您需要split输入或使用Text :: CSV来执行此操作并逐行读取文件。

此外,现在最好将open与三个参数一起使用,并使文件句柄有词汇。

我已经将所有这些都写成了自制CSV处理的例子。如果您的文件更复杂,请阅读Text :: CSV并使用它。

use DBI;
use strict;
use warnings;

my $csv          = "C:/Perl/scripts/table.csv";
# omitted settings here ...

my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1})
  or die "Could not connect to database! $DBI::errstr";
open (my $fh, '<', $csv) 
  or die "Couldn't open csvfile: $!";

# prepare statement handle for reuse in the loop
my $sth = $dbh->prepare(qq{
  INSERT INTO student(stud_id,stud_name,dept_id,stud_mark,stud_address) 
  VALUES (?, ?, ?, ?, ?)});

# read the file line by line
while (my $line = <$fh>) {
  chomp $line; # remove newline
  $sth->execute( split /;/, $line ); # assuming the separator is a semicolon 
}

close $fh;
# DB handle will disconnect implicitly on end of program

如您所见,我决定prepare the statement预先重新使用它。这样可以在循环中节省大量时间,因为DB会记住该语句。

答案 1 :(得分:6)

从列表上下文中的文件句柄(即代码中的<CSV>位)读取文件中的所有行并将其作为列表返回。因此,您的?, ?, ?, ?占位符每个都会从文件中获得整行(包括末尾的换行符)。对于某些字段(可能是dept_id?),这可能不是有效值,因此INSERT语句失败。

虽然实际上,你也将$/设置为undef,这使得它甚至成为了wrongerer。 $/在读取文本文件时更改了Perl的新行概念。将其设置为undef意味着Perl会将整个文件视为一行。

猜测一下,您要做的是一次读取一行CSV文件,并将每个文件泵入数据库。

#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Text::CSV;  # case-sensitive!

my $driver       = "mysql"; 
my $database     = "test";
my $host         = "localhost"
my $databaseport = "3306";
my $userid       = "root";
my $password     = "password";
my $csv          = "C:/Perl/scripts/table.csv";

# Connect to database.
my $dsn = "dbi:mysql:dbname=$databasename;host=$dbhost;port=$dbport;";
my $dbh = DBI->connect($dsn, $userid, $password,{ RaiseError => 1})
  or die "Could not connect to database! $DBI::errstr";

# DBI can be more efficient if you prepare the SQL query once, and then
# execute it multiple times, rather than calling `do` for each insert.
my $sth = $dbh->prepare(<<'SQL');
  INSERT INTO student (stud_id,stud_name,dept_id,stud_mark,stud_address)
  VALUES (NULL, ?, ?, ?, ?)"
SQL

# Open the CSV file.A
open my $CSV, '<', $csv
  or die "Couldn't open csvfile: $!";

# Create an instance of Text::CSV.
my $reader = Text::CSV->new;

# Use Text::CSV to read a line.
while (my $row = $reader->getline($CSV))
{
  # Insert into database.
  $sth->execute( @$row );
}

# Clean up (optional; Perl will do this when your script ends anyway).
$dbh->disconnect;
close $CSV;