【问题标题】:Perl DBI::fetchrow_array() gives empty instead of undef for NULLPerl DBI::fetchrow_array() 为 NULL 提供空而不是 undef
【发布时间】:2017-02-09 22:57:11
【问题描述】:

迁移到新服务器后,在执行 SELECT 查询时,如果请求的列值为 NULL,Perl 的 DBI::fetchrow_array() 返回看似空字符串:defined() 返回 1 和length() 返回 0。

我读到的所有内容都告诉我,我应该从 NULL 中获取 undef,这确实是它在我的旧服务器上的工作方式。新服务器有一个 MySQL 数据库的副本,我使用 Sequel ProExport SQLImport SQL 功能迁移了该数据库,这是一个 MySQL gui我在我的 Mac 上运行。对于这两个数据库,有问题的值在 Sequel Pro 中清楚地显示为灰色 NULL,如果我以交互方式运行 mysql,则显示为 NULL。例如,请参阅此记录中的name

mysql> SELECT * from trials WHERE id = 26069 ;
+-------+----------+-----------+---------+--------+ ...
| id    | language | numTrials | name    | status | ...
+-------+----------+-----------+---------+--------+ ...
| 26069 | en       |         3 | NULL    | Done   | ...
+-------+----------+-----------+---------+--------+ ...
1 row in set (0.00 sec)

我的旧服务器正在运行旧包:

  • Perl 5.10.1 与 5.22.1
  • DBI 1.634 与 1.636
  • DBD::mysql 4.022 与 4.033

这是我在fetchrow_array附近的代码:

@result = $statementHandle->fetchrow_array ;

for my $value (@result) {
    if (! utf8::is_utf8($value)) {
        utf8::decode($value) ;

        # Log values for debugging the NULL/undef issue:
        my $aValue = $value ;
        my $len = length($aValue) ;
        if (!defined($value)) {
            $aValue = "<unnndefined>" ;
        }
        print {*::STDLOG} info => "daValue l=$len : $daValue\n" ;
    }
}

非常感谢任何可以提出建议的人!

【问题讨论】:

    标签: mysql perl dbi


    【解决方案1】:

    您的代码将产生警告

    Use of uninitialized value in subroutine entry
    

    您对utf8::decode($value) 的调用尝试将$value 转换为字符串。如果您将其传递给undef,则该值将被视为空字符串(带有随附的警告)并按此方式解码和存储

    在条件语句中包含所有这些代码似乎很奇怪。当然你只是想要

    utf8::decode($value) if $value and not utf8::is_utf8($value);
    

    然后剩下的代码应该独立于字段的编码状态?

    更好的是,您应该确保DBI 在进出数据库的过程中自动编码和解码字符串,方法是将选项{mysql_enable_utf8mb4 =&gt; 1} 添加到数据库connect 调用中。您还需要将CHARACTER SET utf8mb4 添加到CREATE TABLECREATE DATABASE 语句中。 (不要使用CHARACTER SET utf8;这是真正的UTF-8 的子集,每个字符限制为三个字节。)当然,如果需要,您可以在初始创建后ALTER TABLE

    【讨论】:

    • 宾果游戏。正如您所建议的,只需删除该 utf8::decode($value),我现在就可以按预期得到 undef。
    • 我没有看那个,因为我的旧服务器具有完全相同的代码并且工作正常。正如您所建议的,数据库配置中可能存在一些不同,我需要按照您的解释进行深入研究。多年来,我一直在待办事项清单上整理一些在这个系统中很明显的 UTF8 恶作剧。它对非 ASCII 字符运行良好,但有证据表明多个编程错误正在相互抵消 :((
    • 原来涉及utf8::decode() 的旧代码是一个草率的解决方法,因为该数据库具有存储为 Latin-1 的混蛋 UTF-8 数据。除了完全删除该代码并在connect() 期间启用utf8mb4,我还需要convert the bastard data
    猜你喜欢
    • 2015-03-28
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多