Perl 许多插入语句到 mysql 数据库
Perl many insert statments into mysql database
我目前的 perl 代码如下所示:
@valid = grep { defined($column_mapping{ $headers[$_] }) } 0 .. $#headers;
...
my $sql = sprintf 'INSERT INTO tablename ( %s ) VALUES ( %s )',
join( ',', map { $column_mapping{$_} } @headers[@valid] ),
join( ',', ('?') x scalar @valid);
my $sth = $dbh->prepare($sql);
...
my @row = split /,/, <INPUT>;
$sth->execute( @row[@valid] );
(摘自 mob's 上一个问题。)
这基本上是从 csv 数据动态构建 sql 插入语句,并且只允许从我的列映射中选择具有适当 headers 的 csv 数据。
我一直在寻找有关如何一次插入包含多行数据的语句的示例。
我的 perl 脚本需要 运行 大约几亿条插入语句,一次只做一个似乎真的很慢,尤其是因为我 运行 正在使用它的服务器只有6gb 内存和较慢的互联网连接。
有什么方法可以一次上传多行数据吗?所以一个插入语句可能一次上传 50 行或 100 行?我不知道如何使用 perl DBI。
您可以使用与常规 SQL 相同的语法一次插入多行,但您需要使用 Perl 正确构建您的 INSERT 语句。 Perl 的 slice() 可以帮到你:
假设您有 7 行数据并且想要将它们插入 3 行的块中。 "Regular" SQL 会像这样:
insert into T (col1, col2) values ( 1, 2), ( 3, 4), ( 5, 6);
insert into T (col1, col2) values ( 7, 8), ( 9,10), (11,12);
insert into T (col1, col2) values (13,14);
假设您的 perl 结构是这样的:
my $values = [ [1,2], [3,4], ..., [13,14] ];
如果不是,把它变成这个形状。现在:
use constant CHUNKSIZE => 3;
my $stmt = sprintf( 'insert into T (col1, col2) values %s',
join(',', '(?,?)' x CHUNKSIZE) );
# $stmt is now 'insert into T (col1, col2) values (?,?),(?,?),(?,?)'
my $sth = $dbh->prepare($stmt);
while( my @chunk = splice( @{$values}, 0, CHUNKSIZE ) ) {
# @chunk has 3 elements (rows), or less for the last chunk
if (scalar @chunk == CHUNKSIZE) {
$sth->execute( @chunk ); # inserts 3 rows at once
} else {
# build and prepare a new statement for the remaining rows.
# in our sample there is only 1 remaining row.
$stmt = sprintf( 'insert into T (col1, col2) values %s',
join(',', '(?,?)' x scalar @chunk) );
$sth = $dbh->prepare($stmt);
$sth->execute( @chunk ); # inserts the last row
}
}
my $sql_values = join( ' ', ('(?, ?, ?)') x scalar(@array) );
前面说了,那你压平就行了
我目前的 perl 代码如下所示:
@valid = grep { defined($column_mapping{ $headers[$_] }) } 0 .. $#headers;
...
my $sql = sprintf 'INSERT INTO tablename ( %s ) VALUES ( %s )',
join( ',', map { $column_mapping{$_} } @headers[@valid] ),
join( ',', ('?') x scalar @valid);
my $sth = $dbh->prepare($sql);
...
my @row = split /,/, <INPUT>;
$sth->execute( @row[@valid] );
(摘自 mob's
这基本上是从 csv 数据动态构建 sql 插入语句,并且只允许从我的列映射中选择具有适当 headers 的 csv 数据。
我一直在寻找有关如何一次插入包含多行数据的语句的示例。
我的 perl 脚本需要 运行 大约几亿条插入语句,一次只做一个似乎真的很慢,尤其是因为我 运行 正在使用它的服务器只有6gb 内存和较慢的互联网连接。
有什么方法可以一次上传多行数据吗?所以一个插入语句可能一次上传 50 行或 100 行?我不知道如何使用 perl DBI。
您可以使用与常规 SQL 相同的语法一次插入多行,但您需要使用 Perl 正确构建您的 INSERT 语句。 Perl 的 slice() 可以帮到你:
假设您有 7 行数据并且想要将它们插入 3 行的块中。 "Regular" SQL 会像这样:
insert into T (col1, col2) values ( 1, 2), ( 3, 4), ( 5, 6);
insert into T (col1, col2) values ( 7, 8), ( 9,10), (11,12);
insert into T (col1, col2) values (13,14);
假设您的 perl 结构是这样的:
my $values = [ [1,2], [3,4], ..., [13,14] ];
如果不是,把它变成这个形状。现在:
use constant CHUNKSIZE => 3;
my $stmt = sprintf( 'insert into T (col1, col2) values %s',
join(',', '(?,?)' x CHUNKSIZE) );
# $stmt is now 'insert into T (col1, col2) values (?,?),(?,?),(?,?)'
my $sth = $dbh->prepare($stmt);
while( my @chunk = splice( @{$values}, 0, CHUNKSIZE ) ) {
# @chunk has 3 elements (rows), or less for the last chunk
if (scalar @chunk == CHUNKSIZE) {
$sth->execute( @chunk ); # inserts 3 rows at once
} else {
# build and prepare a new statement for the remaining rows.
# in our sample there is only 1 remaining row.
$stmt = sprintf( 'insert into T (col1, col2) values %s',
join(',', '(?,?)' x scalar @chunk) );
$sth = $dbh->prepare($stmt);
$sth->execute( @chunk ); # inserts the last row
}
}
my $sql_values = join( ' ', ('(?, ?, ?)') x scalar(@array) );
前面说了,那你压平就行了