我有以下代码:
use strict;
use warnings;
use List::Util qw(max);
use DateTime;
use JSON;
use DBI;
...
my @names = @{ select_users_to_update('last_name') };
sub select_users_to_update {
my ( $self, $column ) = @_;
my $sql = qq{
SELECT DISTINCT `$column`
FROM `db_name`
WHERE `first_name` IS NULL
};
my $rows = $self->{dbh}->selectall_arrayref( $sql, { Slice => {} } );
my @fields = map { $_->{$column} } @$rows;
return \@fields;
}
我收到以下错误:
Can't use string ("last_name") as a HASH ref while "strict refs" in use at update_hpcdb_people.pm line 51.
此代码取自不同的脚本,其中表现良好。我对perl对map命令的反对感到困惑 - 上面的代码出了什么问题?
答案 0 :(得分:10)
TL; DR:假设省略的代码包含这样的内容以连接到数据库:
my $dbh = DBI->connect(....);
然后像这样改变对select_users_to_update
的调用就可以了:
my @names = @{ select_users_to_update( { dbh => $dbh }, 'last_name') };
解释如下。
select_users_to_update
子例程期望其第一个参数($self
)是对包含dbh
字段的哈希的引用,该字段的值是数据库连接的句柄。你没有传递任何这样的东西;你传递的只是列名。
它可能来自一个带有自定义模块的程序,它被编写为对象类,用于处理数据库内容。 select_users_to_update
子例程是作为类的一个方法编写的,所以我猜测原始程序中的代码执行你想要做的事情会是这样的:
my $customObj = CustomClass->new( database parameters ... );
my @names = @{ $customObj->select_users_to_update('last_name') };
由于使用方法语法$someRef->subname
调用子例程与将$someRef
作为第一个参数传递相同,因此$customObj
中的引用将在子例程内变为$self
。只要构造函数CustomClass::new
在引用的Hash中填充dbh
,它就可以按设计工作。
但如果您不需要它,并且只想使用一个子例程,则不必复制所有额外的代码。您可以按原样重复使用TL中的代码;上面的DR。
或者,您可以稍微修改子例程,因此它只需要直接使用未经修饰的数据库句柄,而不是在hashref中查找它:
my @names = @{ select_users_to_update( $dbh, 'last_name') };
sub select_users_to_update {
my ( $dbh, $column ) = @_;
...
my $rows = $dbh->selectall_arrayref( $sql, { Slice => {} } );
...
}
现在不是自定义类的方法,而是有一个可以与任何旧DBI对象一起使用的独立子例程。