使用Perl的DBI批量插入

时间:2015-11-17 22:04:53

标签: perl postgresql

我正在尝试将数据行批量插入到postgres数据库中。

我认为我在数组引用中填充了数据。它是使用Spreadsheet::BasicReadNamedColmodule从空格分隔文件中使用perl脚本获取的。获取数据的代码是

 $ss = new Spreadsheet::BasicReadNamedCol($xlsFileName) ||
 die "Could not open '$xlsFileName': $!";
 $ss->setColumns(@columnHeadings);

 my @array;

 my $row = 0;
 while (my $data = $ss->getNextRow())
 {
     $row++;

     push @array, "@$data";
 }

以下是数组引用的内容。

Cristan McX  123 W State Street North Aurora IL
William Sch  123 South Third St #367 Geneva IL
Kellie xxx  123 South East St. Gardner IL
John xx  321 Princeton Ct. Frankfort IL
Peter xxxxxxx  123 N Myrtle Avenue Elmhurst IL
Izabella xxx  321 S 3rd St. #367 Geneva IL

我用来插入的Perl DBI代码是:

my $dbh = DBI->connect("DBI:Pg:dbname=greenthumb;host=localhost;    port=5432","","", {'RaiseError' => 1});

my $sth = $dbh->prepare( 'INSERT INTO testtable (?, ?, ?, ?, ?, ?)' );

foreach(@array) { $sth->execute( @{$_} ); }
$sth->finish;

我得到的错误是:

Can't use string ("FirstName LastName BusinessName "...) as an ARRAY ref   while "strict refs" in use at ./f.pl line 38.

3 个答案:

答案 0 :(得分:2)

不是一般的DBI解决方案,但由于您使用的是PostgreSQL,您还可以使用" COPY"对于有效的批量插入,在从电子表格中抓取每一行时添加每一行:

...
$dbh->do("COPY testtable FROM STDIN");
while ( my $data = $ss->getNextRow ) {
    $dbh->pg_putcopydata(join("\t", @$data) . "\n");
}
$dbh->pg_putcopyend();

答案 1 :(得分:1)

考虑到您在评论中收到的建议并添加了一些我自己的更正,您的程序应该是这样的。我无法通过平板电脑发布来测试它

无需将整个电子表格读入内存 - 只需在从XLS文件中读取数据时将数据插入数据库表

显然,您必须使用真实值替换列名称。如果您只是想要电子表格中的所有数据,那么您应该使用Spreadsheet::BasicRead

use strict;
use warnings 'all';

use DBI;
use DBD::Pg;
use Spreadsheet::BasicReadNamedCol;

use constant XLS_FILE => 'myfile.xls';

my $dbh    = DBI->connect( 'dbi:Pg:dbname=greenthumb;host=localhost;port=5432', '', '', { RaiseError => 1 } );
my $insert = $dbh->prepare( 'INSERT INTO testtable VALUES (?, ?, ?, ?, ?, ?)' );

my $ss = Spreadsheet::BasicReadNamedCol->new(
    fileName      => XLS_FILE,
    columns       => [ qw/ FirstName LastName BusinessName col4name col5name col6name / ],
    skipHeadings  => 1,
    skipBlankRows => 1,
) or die sprintf "Could not open '%s': %s", XLS_FILE, $!;

while ( my $data = $ss->getNextRow ) {
    $insert->execute(@$data);
}

答案 2 :(得分:0)

你从$ss->getNextRow获得了一个数组引用,但你取消引用它并在将数组推送到数组时将数组转换为字符串。

push @array, "@$data";

@$data取消引用引用的数组,"..."将解除引用的数组转换为字符串。)

如果您只是推送了您拥有的数组引用,那么一切都会正常工作。

push @array, $data;

但我喜欢Borodin' answer,因为它消除了对中间@array的需要,并在一行处理电子表格。