perl - map not working,"不能使用string ...作为HASH ref"

She*_*rSt 0 perl hash map

我有以下代码:

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;
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Can't use string ("last_name") as a HASH ref while "strict refs" in use at update_hpcdb_people.pm line 51.
Run Code Online (Sandbox Code Playgroud)

此代码取自不同的脚本,其中表现良好.我对perl对map命令的反对感到困惑 - 上面的代码出了什么问题?

Mar*_*eed 10

TL; DR:假设已省略的代码包含这样的内容以连接到数据库:

my $dbh = DBI->connect(....);
Run Code Online (Sandbox Code Playgroud)

然后改变这样的调用select_users_to_update就可以了:

my @names = @{ select_users_to_update( { dbh => $dbh }, 'last_name') };
Run Code Online (Sandbox Code Playgroud)

解释如下.

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') };
Run Code Online (Sandbox Code Playgroud)

由于使用方法语法调用子例程$someRef->subname与作为$someRef第一个参数传递相同,因此引用$customObj$self进入子例程.只要构造函数CustomClass::new填充dbh在引用的Hash中,它就可以按设计工作.

但是,如果您不需要它,并且只想使用一个子例程,则不必复制所有额外的代码.您可以按照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 => {} } );
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用独立的子程序代替自定义类的方法,该子程序可以与任何旧的DBI对象一起使用.