【问题标题】:How do I insert null fields with Perl's DBD::Pg?如何使用 Perl 的 DBD::Pg 插入空字段?
【发布时间】:2010-05-18 16:44:58
【问题描述】:

我有一个 Perl 脚本根据管道分隔的文本文件将数据插入 Postgres。有时,字段为空(如预期的那样)。但是,Perl 将这个字段变成了一个空字符串,并且 Postgres 的插入语句失败了。

这是一段代码:


use DBI;

#Connect to the database.
$dbh=DBI->connect('dbi:Pg:dbname=mydb','mydb','mydb',{AutoCommit=>1,RaiseError=>1,PrintError=>1});

#Prepare an insert.
$sth=$dbh->prepare("INSERT INTO mytable (field0,field1) SELECT ?,?");

while (<>){
    #Remove the whitespace
    chomp;

    #Parse the fields.
    @field=split(/\|/,$_);

    print "$_\n";

    #Do the insert.
    $sth->execute($field[0],$field[1]);
}

如果输入是: 罢工>

一个|1 乙| c|3

编辑:改用这个输入。

一个|1|x b||x c|3|x

它将在b| 失败。

DBD::Pg::st 执行失败:错误:整数输入语法无效:“”

我只想让它在 field1 上插入一个空值。有什么想法吗?

编辑:我在最后一分钟简化了输入。由于某种原因,旧的输入实际上使它起作用。所以现在我将输入更改为会使程序失败的东西。另请注意,field1 是可为空的整数数据类型。

【问题讨论】:

  • 这段代码在这里工作,Perl 5.10.1,DBD::Pg 2.15.1,Postgres 8.4。另外,您为什么要使用 SELECT ?,?而不是 VALUES (?,?)?
  • 另外,使用严格;使用警告;并修复你的变量声明
  • 关于 SQL 格式..实际代码实际上在该选择上有一些连接。

标签: perl postgresql dbi


【解决方案1】:

我不确定您是否测试了粘贴的代码和数据是否一起使用,它们适用于 Perl 5.10.1、DBD::Pg 2.15.1 和 Postgres 8.4。此外,您应该使用严格和警告,而不是依赖于变量的包范围。

如果您更改代码和数据以使用三个或更多字段,将非终端字段留空,则可以从 DBD::Pg 触发错误。在执行准备好的语句之前,在代码中添加这样的一行:

map { $_ eq '' and $_ = undef } @field;

将@field 中的空字符串映射到undef

【讨论】:

  • 它负责将空字符串转换为空值。奇怪的是,删除输入中的字段会导致空字符串变为 null(至少看起来已经发生了)。
  • 如果字符串以您要拆分的字符结尾,例如 'a|4|'那么最后的数组元素根本没有被填充,没有变成空字符串,所以是undef,见perldoc -f split。
【解决方案2】:

DBI 包将undef 映射到NULL。 (Perl 的定义与错误逻辑实际上非常适合 SQL 的三元逻辑。)

因此,在您的 while 循环中,只需检查指示的字段是否为空字符串,如果是,则改为 undef

while (<>){
    ...
    #Parse the fields.
    @field=split(/\|/,$_);

    if ( $field[1] eq '' ) { 
        # handle NULLs
        $field[1] = undef;
    }

    #Do the insert.
    $sth->execute($field[0],$field[1]);
}

【讨论】:

  • 你的 if 永远不会是真的,如果你把 use strict;使用警告;在您的代码中,您会得到“在字符串 eq 中使用未初始化的值 $field[1]”
  • @james,我不确定你的意思。它在启用strictwarnings 的情况下运行良好,并且条件成功。 perl -Mstrict -Mwarnings -MData::Dumper -le 'my $str="a|b||d"; my @a = split /\|/, $str; if ( $a[2] eq "" ) { $a[2] = undef; }; print Dumper \@a'
  • 它现在可以工作了,但是正如最初提出的问题(并且正如你回答的那样),只有 2 个字段,最后是空字段,返回该索引的 undef。
【解决方案3】:

undef 通常映射为 NULL。看起来您插入的空字符串与undef 不同。

【讨论】:

  • 这对 oracle 也是如此{null maps to undef} 我需要很长时间才能找到并且我的代码会因为你而看起来更简单谢谢你
猜你喜欢
  • 1970-01-01
  • 2013-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
  • 2011-11-08
  • 2011-04-28
  • 2019-11-12
相关资源
最近更新 更多