我有以下非常复杂的Perl代码,它由大小不等但通常在10到20行之间的动态数组提供。因此我在循环中运行它,但是估计必须有一种更优雅的方式来插入数据。
是否可以改进此代码以提高效率?
sub data_fill {
my $target = shift;
my (@input_data) = @_;
# Delete the old data
my $sth = $dbh->prepare("DELETE FROM work_data WHERE target = '$target' ");
$sth->execute();
# Insert the new data
my $sql = qq{INSERT INTO work_data (target, trackingno, temp, apple, orange, banana, strawberry, lettuce, apricot, peach, blackberry, melon, lemon) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)};
my $sth = $dbh->prepare($sql);
my $arraysize = scalar(@input_data);
my $i = 0;
while ($i < $arraysize) {
$sth->bind_param(1, $target, SQL_VARCHAR);
$sth->bind_param(2, 'OK', SQL_VARCHAR);
$sth->bind_param(3, $input_data[$i], SQL_VARCHAR);
$sth->bind_param(4, $input_data[$i + 1], SQL_VARCHAR);
$sth->bind_param(5, $input_data[$i + 2], SQL_VARCHAR);
$sth->bind_param(6, $input_data[$i + 3], SQL_VARCHAR);
$sth->bind_param(7, $input_data[$i + 4], SQL_VARCHAR);
my $lettuce = $input_data[$i + 5];
my $apricot = $input_data[$i + 6];
my $peach = $input_data[$i + 7];
if (length($lettuce) == 0) {
$lettuce = -1;
} # Safety net to help later in db sorting
if (length($apricot) == 0) {
$apricot = -1;
} # Safety net to help later in db sorting
if (length($peach) == 0) {
$peach = -1;
} # Safety net to help later in db sorting
$sth->bind_param(8, $lettuce, SQL_INTEGER);
$sth->bind_param(9, $apricot, SQL_INTEGER);
$sth->bind_param(10, $peach, SQL_INTEGER);
$sth->bind_param(11, $input_data[$i + 8], SQL_VARCHAR);
$sth->bind_param(12, $input_data[$i + 9], SQL_VARCHAR);
$sth->bind_param(13, $input_data[$i + 10], SQL_VARCHAR);
$sth->execute;
$i = $i + 11; # INCREMENT
}
$dbh->disconnect;
return;
}
答案 0 :(得分:2)
你的代码并不像复杂的那样复杂。
我看到的第一件事是每次子程序执行时都会调用$dbh->prepare
。更糟糕的是,返回前有一个$dbh->disconnect
。
我还会看一下绑定,如果你将参数复制到一个静态数组而不是每次都绑定它们,这可能是永久性的。
<强>更新强>
这是为了解释我的意思。 unless
语句中的代码只会执行一次 - 第一次调用data_fill
子例程。它准备delete和insert语句,并将@params
数组绑定到insert语句中的占位符。
请注意,prepare
和bind_param
来电不必在此子程序中。它们实际上是初始化的一部分,unless
用于确保它们只执行一次。
完成所有设置之后,剩下的就是执行delete
语句,然后从子例程参数列表中重复填充@params
数组并执行insert
语句。我完全删除了$dbh->close
,因为它不是关闭数据库句柄的正确位置。
此解决方案中包含太多&#34;魔术数字&#34; ,我不会按原样发布它,但我不够了解你的要求总结我是否在正确的界限上。
请注意,除了检查它是否会编译
之外,这些都没有经过测试my ($delete, $insert, @params);
sub data_fill {
my $target = shift;
my (@input_data) = @_;
unless ($delete and $insert) {
$delete = $dbh->prepare('DELETE FROM work_data WHERE target = ?');
$insert = $dbh->prepare('
INSERT INTO work_data (
target, trackingno, temp, apple, orange, banana,
strawberry, lettuce, apricot, peach, blackberry, melon, lemon
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
');
for my $i (0 .. 10) {
my $mode = SQL_VARCHAR;
$mode = SQL_INTEGER if $i >= 7 and $i <= 9;
$sth->bind_param($i+1, $params[$i], $mode);
}
}
$delete->execute($target);
while (@input_data >= 11) {
my @record = splice @input_data, 0, 11;
@params = ($target, 'OK', @record);
for (@params[7..9]) {
$_ = -1 unless length > 0;
}
$insert->execute;
}
}