地图不起作用,"Can't use string ... as a HASH ref"



我有以下代码:

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命令感到困惑——上面的代码出了什么问题?

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字段的Hash的引用,该字段的值是数据库连接的句柄。你没有把这样的事情传给它;您传递的只是列名。

它可能来自一个带有自定义模块的程序,该模块作为对象类编写,用于处理数据库内容。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对象一起使用,而不是自定义类的方法。

最新更新