You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl如何获取二维数组?Mojolicious查询数据库报fetch未执行错误

问题描述

我尝试在Perl中获取二维数组时遇到数据库错误,但调试过程中可以看到返回了正确的值。
相关代码如下:

my $worker_names = $self->glpi->db->query(
        'select user_name from report_users'
    );
 
    my @all = @{$worker_names->arrays->flatten->to_array};
 
    if ($worker_name ne '') {
        @all = ( $worker_name );
    }
 
    # name => [ public, privat, phabricator ]
    my $table;
    for my $user_name (@all) {
        $table->{$user_name}->[0] = '00 Stunden 00 Minuten';
        $table->{$user_name}->[1] = '00 Stunden 00 Minuten';
        $table->{$user_name}->[2] = '00 Stunden 00 Minuten';
    }
 
    $glpi_hours->hashes->each( sub {
        my $row = $_[0];
 
        $table->{$row->{'name'}}->[0] = $row->{'public_actiontime'};
        $table->{$row->{'name'}}->[1] = $row->{'private_actiontime'};
    });
 
    $phabricator_hours->hashes->each( sub {
        my $row = $_[0];
 
        $table->{$row->{'name'}}->[2] = $row->{'phab_time'};
    });

收到的错误信息如下:

DBD::mysql::st fetchrow_hashref failed: fetch() without execute() at /var/www/perl5/perlbrew/perls/perl-5.28.3/lib/site_perl/5.28.3/Mojo/mysql/Results.pm line 55.       
  # Fetch sql data
52
  my $hash = $to->{type} eq 'hash';
53   
  my $sql_data
54
    = $to->{list} && $hash ? $self->sth->fetchall_arrayref({})
55  
    : $to->{list}          ? $self->sth->fetchall_arrayref
56   
    : $hash                ? [$self->sth->fetchrow_hashref]
57
    :                        [$self->sth->fetchrow_arrayref];
58
59
  # Optionally expand
60
  if ($mode) {

我定位到问题出在my @all = @{$worker_names->arrays->flatten->to_array};这行代码,没有按照预期运行。我使用的开发框架为Mojolicious。
当我在浏览器中运行代码时,首先会出现上述错误,之后可以看到查询获取到的值已经存储在stash中。

解决方案
  • 错误原因:
    这个报错是Mojo::mysql的常见问题,本质是对已经消费完毕、处于关闭状态的结果集句柄再次执行读取操作,或者SQL执行失败后直接读取无效的结果集。
  • 修复步骤:
  1. 先增加SQL执行错误判断,避免查询失败后直接操作结果集:
my $worker_names = $self->glpi->db->query('select user_name from report_users');
# 先判断查询是否出错
my $error = $self->glpi->db->error;
die "数据库查询失败: $error->[1]" if $error;
  1. 调整结果集读取写法,Mojo::Collection的flatten方法可以直接返回展开的列表,不需要额外调用to_array再解引用,避免多余的结果集操作:
# 修改前
# my @all = @{$worker_names->arrays->flatten->to_array};
# 修改后
my @all = $worker_names->arrays->flatten->each;
  1. 检查后续代码逻辑,确保不会重复使用$worker_names这个结果集对象。Mojo::mysql的Results对象属于一次性消费资源,调用arrays/hashes等方法读取完数据后,底层的数据库句柄就会被关闭,再次读取就会触发该报错。如果后续需要用到这份用户名数据,直接使用已经读取好的@all数组即可。

你看到报错后stash中仍有数据,是因为该错误默认以警告形式抛出,不会直接终止程序运行,后续的stash赋值逻辑仍会执行。

内容的提问来源于stack exchange,提问作者Dex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 07:24:03