从包含一些空列的 Informix 表中选择所有行

Posted

技术标签:

【中文标题】从包含一些空列的 Informix 表中选择所有行【英文标题】:Selecting all rows from Informix table containing some null columns 【发布时间】:2015-05-28 17:50:18 【问题描述】:

我正在使用 Perl DBD::ODBC 连接到一个 Informix 数据库,我以前对它的架构视而不见。我已经通过查询 tabname 和 colname 表成功地发现了架构。我现在遍历每个表,提取其中的所有内容以加载到另一个模型中。我发现空列退出了选择查询。例如。如果一个表看起来像这样,带有一个可选的 null lastseen 列(任何数据类型):

ID    username    lastseen
--    --------    --------
1     joe         1234567890
2     bob         1098765432
3     mary        
4     jane        1246803579

然后select * from mytable(或单独指定所有列名)停在ma​​ry行。

我确实通过如下使用 NVL 来完成这项工作:

select nvl(id, ''), nvl(username, ''), nvl(lastseen, '') from mytable

好的,但是我的问题是:是否有更简单的 Informix 语法允许空值进入我的结果集,就像NULLS OK 或我错过了什么?或者,某些数据库句柄选项是否允许相同?

这是我的 Perl 与 nvl() hack 的示例,以防相关:

my %tables = (
    users => [
        qw(id username lastseen)
    ]
);

foreach my $tbl (sort keys %tables) 
    my $sql = 'select ' . join(',', map  "nvl($_, '')"  @$tables$tbl) . " from $tbl";
    # sql like: select nvl(a, ''), nvl(b, ''), ...
    my $sth = $dbh->prepare($sql);
    $sth->execute;
    while(defined(my $row = $sth->fetchrow_arrayref)) 
        # do ETL stuff with $row
    

【问题讨论】:

这真的没有必要。当然 DBD::Informix 可以正确处理 NULL 值 - 你有充分的理由不能使用那个驱动程序而不是 ODBC 驱动程序吗? 半好,只是我处于一个非常庞大且偏执的企业环境中,安装新模块实际上是一个巨大的痛苦,可能不值得为这个有限的应用程序付出努力,因为我确实有一种解决方法。我们还有其他解决方案类似地使用 ODBC 来抽象数据库层,所以我当然有兴趣了解它的局限性和怪癖,如果这确实是罪魁祸首(我非常愿意相信它是)。 【参考方案1】:

在安装 DBD::Informix 的尝试失败后,我回到了这个问题,发现由于某种原因在数据库句柄上启用 LongTruncOk 确实允许选择所有行,包括那些具有空列的行。我不认为这是问题的根源,但它在这里起作用。

然而,这个解决方案似乎与一个不相关的语言环境调整相冲突,以支持非 ascii 字符。我在我的连接字符串中添加了DB_LOCALE=en_us.utf8CLIENT_LOCALE=en_us.utf8,以防止在遇到非ascii 字符时选择类似地中断(即,在结果集中说500,其中第300 行有一个非ascii 字符,后面的200 行会不予退还)。以这种方式设置语言环境以及在 dbh 上启用 LongTruncOk 后,所有行都将被返回(没有 NVL hack),但空列从前一行添加了字节,而不是以任何明显的模式我。当我离开连接字符串的区域设置并设置 LongTruncOk 时,正确选择了具有空列的行,但具有 utf 字符的行会中断。

因此,如果您没有字符集问题,也许 LongTruncOk 对您有用。出于我的目的,我不得不继续使用NVL 解决方法来处理空值并指定字符的语言环境。

【讨论】:

【参考方案2】:

检查this - Perl 中的 NULL 部分。看来有了这个驱动就没有简单的办法来处理这个问题了。

【讨论】:

以上是关于从包含一些空列的 Informix 表中选择所有行的主要内容,如果未能解决你的问题,请参考以下文章

选择 PL/SQL 中两个非空列值之间的行集

从多个表中过滤并删除空列

如何从包含日期时间列的表中获取某些行和“先前”行?

Linq MVC5 MSQL 从包含大量列的表中选择一些列,以便更好更快地查询

用 Oracle 中同一张表中的其他行数据更新一行

如何从一个表中选择不在其他表中的所有行?