如何使用 Perl 的 DBD::Pg 插入空字段?

发布于 2024-09-02 07:43:26 字数 970 浏览 6 评论 0原文

我有一个 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]);
}

如果输入是:

a|1
b|
c|3

编辑:改用此输入。

a|1|x
b||x
c|3|x

它将在 b| 处失败。

DBD::Pg::st execute failed: ERROR:  invalid input syntax for integer: ""

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

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

I have a Perl script inserting data into Postgres according to a pipe delimited text file. Sometimes, a field is null (as expected). However, Perl makes this field into an empty string and the Postgres insert statement fails.

Here's a snippet of code:


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]);
}

And if the input is:

a|1
b|
c|3

EDIT: Use this input instead.

a|1|x
b||x
c|3|x

It will fail at b|.

DBD::Pg::st execute failed: ERROR:  invalid input syntax for integer: ""

I just want it to insert a null on field1 instead. Any ideas?

EDIT: I simplified the input at the last minute. The old input actually made it work for some reason. So now I changed the input to something that will make the program fail. Also note that field1 is a nullable integer datatype.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

埋情葬爱 2024-09-09 07:43:26

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

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

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

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

I'm not sure you tested whether your pasted code and data together, they work with Perl 5.10.1, DBD::Pg 2.15.1 and Postgres 8.4. Also you should use strict and warnings and not rely on package scope for your variables.

If you change your code and data to use three or more fields, leaving a non-terminal one empty, then you can trigger the error from DBD::Pg. Add a line like this to your code before executing the prepared statement:

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

To map empty strings in @field to undef

大姐,你呐 2024-09-09 07:43:26

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]);
}

The DBI package maps undef to NULL. (Perl's defined-ness vs. falseness logic is actually a pretty good fit for SQL's trinary logic.)

So, in your while loop, just check if the indicated field is an empty string, and if so, make it undef instead:

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

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

    #Do the insert.
    $sth->execute($field[0],$field[1]);
}
随梦而飞# 2024-09-09 07:43:26

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

undef usually maps to NULL. It looks like you're inserting the empty string which is not the same as undef.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文