Perl数据库间转移

时间:2014-04-02 17:58:22

标签: perl

我是Perl的新手,我尝试从MySQL表StoreEvent中选择数据并使用DBI模块将其插入StoreEvent2。

#!/usr/bin/perl

use DBI;
$dbh = DBI->connect('dbi:mysql:db_m2','root','rootboot')
or die "Connection Error: $DBI::errstr\n";
$sth = $dbh->prepare("select * from StoreEvent limit 10");
$sth->execute
or die "SQL Error: $DBI::errstr\n";
while (@row = $sth->fetchrow_array) {
print "@row\n";
}

输出如下:

# ./perl_data_dumper.pl
26152 2 1366735974109 1366735982127 9510 0
26153 2 1366735974614 1366735982639 9510 0
26154 2 1366735974613 1366735982637 9510 0
26155 2 1366735974614 1366735982639 9510 0
26156 2 1366735975621 1366735983642 9510 0
26157 2 1366735975621 1366735983643 9510 0
26158 2 1366735977133 1366735985160 9510 0
26159 2 1366735977134 1366735985164 9510 0
26160 2 1366735977637 1366735985659 9510 0
26161 2 1366735977639 1366735985673 9510 0

我不确定如何从第一个查询中获取结果并将其插入到另一个表中。

这是我尝试过的事情

use DBI;
$dbh = DBI->connect('dbi:mysql:db_m2','root','root')
or die "Connection Error: $DBI::errstr\n";
$sth = $dbh->prepare("select * from StoreEvent limit 10");
$sth->execute
or die "SQL Error: $DBI::errstr\n";
while (@row = $sth->fetchrow_array) {
print "@row\n";
}

$dbh2 = DBI->connect('dbi:mysql:db_m2','root','root')
or die "Connection Error: $DBI::errstr\n";
$sth2 = $dbh2->prepare("INSERT INTO StoreEvent2      (StoreID,StoreType,EventStart,EventEnd,AppserverID,Number") VALUES (?,?,?,?,?,?) );
$sth2->execute
or die "SQL Error: $DBI::errstr\n";
while (@row = $sth->fetchrow_array) {
print "@row\n";
}

它不是很正常,我想知道是否有人可以给我一些见解。

谢谢

2 个答案:

答案 0 :(得分:3)

一些事情

  • use strict;use warnings;。永远使用它们。
  • 如果这些表位于同一个数据库中,则只需重用数据库句柄。
  • 您实际上并没有尝试在第一个循环中插入任何内容,而您的第二个循环只是虚假。

清理:

use strict;
use warnings;

use DBI;

my $dbh = DBI->connect('dbi:mysql:db_m2','root','root')
    or die "Connection Error: $DBI::errstr\n";

my $sth = $dbh->prepare("select * from StoreEvent limit 10");
$sth->execute or die "SQL Error: $DBI::errstr\n";

my $sth2 = $dbh2->prepare("INSERT INTO StoreEvent2 (StoreID,StoreType,EventStart,EventEnd,AppserverID,Number") VALUES (?,?,?,?,?,?) );

while (@row = $sth->fetchrow_array) {
    print "@row\n";
    $sth2->execute(@row) or die $dbh->errstr;
}

请注意,由于以下几个原因,此代码仍然很脆弱:

  • 您没有指定StoreEvent所需的列,而是依赖于*
    • 如果表格被更改,可能会有更多列,而不是您现在尝试INSERT到StoreEvent2中的列数。
    • 可能会按照与您在StoreEvent2
    • 中指定的顺序不同的顺序提取列
  • 您正在基于可能的主键(StoreID)进行插入,而不检查该记录是否已存在。

答案 1 :(得分:1)

Miller pointed out您的代码存在许多问题。我想补充说,您可以使用MySQL INSERT ... SELECT syntax在单个查询中执行此操作:

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use DBI;

my $dbh = DBI->connect('DBI:mysql:db_m2', 'root', 'root', { RaiseError => 1 });

my $statement = <<'STATEMENT';
    INSERT INTO StoreEvent2 (StoreID, StoreType, EventStart, EventEnd, AppserverID, Number)
      SELECT StoreEvent.StoreID, StoreEvent.StoreType, StoreEvent.EventStart, StoreEvent.EventEnd, StoreEvent.AppserverID, StoreEvent.Number
      FROM StoreEvent
STATEMENT

my $rows = $dbh->do($statement);
say "Inserted $rows rows";

$dbh->disconnect;

我假设两个列中的列名相同,但如果查询不是,则可以调整查询。附加说明:

  • 如果您将INSERT更改为INSERT IGNORE,则会忽略会导致重复键违规的行。
  • 上面的查询会复制第一个表中的所有行。您可以通过指定WHERE子句来限制要复制的行。我不像你在原始代码中那样单独使用LIMIT,因为它只是抓取一组随机的行。
  • connect中设置RaiseError会导致在出现错误时引发异常,因此您不必在每次数据库操作后添加or die ...
  • 如果您要在程序中多次运行此查询,请使用prepareexecute代替do