Mysql插入包含双逗号的值

时间:2016-06-19 18:40:09

标签: mysql perl csv sql-insert

我尝试逐行将值插入到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";
    }
}

5 个答案:

答案 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'

这是用编程语言完成的。完成此步骤后,插入数据没有问题。