我尝试逐行将值插入到MySQL
表中,该表从CSV
中的Perl
文件中读取。如果CSV文件中的任何字段为空,则会有两个连续的逗号。 E.g。
Firstname,Lastname,Code,Phone,Email
fname1,lname1,123,34543,f1@gmail.com
fname2,lname2,344,45645,f2@gmail.com
fname3,lname3,454,,f3@gmail.com
在第三行,没有电话号码。所以有两个连续的逗号。当我们尝试使用以下命令插入mysql时,它会失败。
insert into table1 (Firstname,Lastname,Code,Phone,Email) values (fname3,lname3,454,,f3@gmail.com)
怎么做?
我使用了以下代码来执行此操作。
open CSV, $file or die $!;
my @csv_content = <CSV>;
close CSV;
my $fields = "Firstname,Lastname,Code,Phone,Email";
my $table = "table1";
my $csv = Text::CSV->new();
foreach(@csv_content){
if($csv->parse($_)){
my @values = $csv->fields();
my $status = $csv->combine(@values);
my $line = $csv->string();
$statement = "INSERT INTO $table($fields) VALUES($line);";
$sth = $dbh->prepare( $statement );
$sth->execute() or die "$! $DBI::errstr";
}
}
答案 0 :(得分:1)
我可能会这样写。我在你的csv文件中包含了空字段。我使用了5个占位符,'?',并没有在循环内准备。只需在循环中执行即可。
my $csv = Text::CSV->new ( { binary => 1, eol => "\n" } );
my $file = 'blahblah';
open my $fh, $file or die "$file open failed: $!";
my $dbh = DBI->connect("dbi:SQLite:dbname=pedro.lite","","",
{PrintError => 1, AutoCommit => 0}) or die "Can't connect";
my $sth = $dbh->prepare(q{INSERT INTO table1 VALUES(?,?,?,?,?)})
or die $dbh->errstr;
<$fh>; # throw away header - first line
while (my $row = $csv->getline ($fh)) {
$sth->execute(@$row) or die $sth->errstr;
}
$dbh->commit or die $dbh->errstr;
close $fh or die "$file close failed: $!";
$sth->finish;
如果文件开头没有标题,请不要使用该行代码。
更新:这是我用来创建数据库的实际程序(使用SQLite),它运行正常,即使是双逗号(空字段)。
#!/usr/bin/perl
use strict;
use warnings;
use Text::CSV_XS;
use DBI;
my $csv = Text::CSV_XS->new ( { binary => 1, eol => "\n" } );
my $file = 'j1.csv';
open my $fh, $file or die "$file open failed: $!";
my $dbh = DBI->connect("dbi:SQLite:dbname=pedro.lite","","",
{RaiseError => 1, PrintError => 0, AutoCommit => 0}) or die "Can't connect";
$dbh->do('DROP TABLE IF EXISTS table1');
$dbh->do(<<EOF);
CREATE TABLE table1 (
Firstname TEXT,
Lastname TEXT,
Code INTEGER,
Phone INTEGER,
Email TEXT)
EOF
my $sth = $dbh->prepare(q{INSERT INTO table1 VALUES(?,?,?,?,?)});
<$fh>; # throw away header - first line
while (my $row = $csv->getline ($fh)) {
$sth->execute(@$row);
}
$sth->finish;
$dbh->commit;
$dbh->disconnect;
close $fh or die "$file close failed: $!";
这是table1查询的输出。
sqlite> .mode column
sqlite> .width 10 10 10 10 14
sqlite> .headers on
sqlite> select * from table1;
Firstname Lastname Code Phone Email
---------- ---------- ---------- ---------- --------------
fname1 lname1 123 34543 f1@gmail.com
fname2 lname2 344 45645 f2@gmail.com
fname3 lname3 454 f3@gmail.com
sqlite>
如您所见,它正确显示fname3没有电话号码。 我使用您的数据就像在帖子中显示INSERT到table1一样。
答案 1 :(得分:1)
计算机无法理解您要插入的内容,因为它无法理解两个逗号之间存在空值。如果您是从perl
开始执行此操作,请尝试将每个值括在quotes
中,即使是空值也是如此。有关数据行3中的示例,请更改
fname3,lname3,454,,f3@gmail.com
到
'fname3','lname3','454','','f3@gmail.com'
这很容易用任何编程语言实现。现在尝试插入。它不会抛出异常,因为它们之间的部分将是空字符串。
答案 2 :(得分:1)
用倒置逗号括起每个值,如'fname3','lname3','454','','f3 @gmail.com'。请注意逗号之间的空引号。这样就可以了解
答案 3 :(得分:0)
加载此类数据的更好方法可能是使用mysql命令LOAD DATA INFILE
:
LOAD DATA INFILE "yourfilename" INTO TABLE "yourtablename" COLUMNS TERMINATED BY ",";
因此完全避免了问题
答案 4 :(得分:0)
我用另一种方法解决了这个问题:首先用倒置的引号括起每个字段,甚至是空字段。封闭在引号后的数据如下所示:
'fname1','lname1','123','34543','f1@gmail.com'
'fname2','lname2','344','45645','f2@gmail.com'
'fname3','lname3','454','','f3@gmail.com'
这是用编程语言完成的。完成此步骤后,插入数据没有问题。