PostgreSQL pl/perl 触发器,区分 null 和空

Jaf*_*foy 5 postgresql trigger null perl

我一直在尝试加快我在 pl/pgsql 中编写的通用审计触发器的速度。更新时,它会生成正在更新的表中的列列表,并在审计表中插入记录任何更改的行(按表、列、之前的数据、之后的数据等)。跨多个表使用相同的触发器函数。

我正在尝试使用 pl/perl,因为它对于手头的任务似乎要快得多,但我似乎遇到了区分数据库中 NULL 和空字符串 ('') 值的问题。

在我看来,如果一列从 NULL 变为空字符串(反之亦然),这是我需要记录的更改。但是,使用可用的新/旧列引用 ($_TD->{new/old}{$columnName}),我似乎无法区分实际为空的列和包含空字符串的列。我知道为空的列正在被空和 undef 检查捕获,我知道的列也是空的。

    if($_TD->{new}{$column} eq '') {
        elog(NOTICE, "New value in column $column is empty");
    }
    if($_TD->{old}{$column} eq '') {
        elog(NOTICE, "Old value in column $column is empty");
    }
    if($_TD->{new}{$column} eq undef) {
        elog(NOTICE, "New value in column $column is not defined");
    }
    if($_TD->{old}{$column} eq undef) {
        elog(NOTICE, "Old value in column $column is not defined");
    }
Run Code Online (Sandbox Code Playgroud)

我怀疑我在这里做了一些愚蠢的事情,但也许我正在尝试做一些我根本无法做的事情。有什么建议吗?

编辑 - 使用 Postgres 8.4.4 的价值

编辑 - 在查看下面 filiprem 的帖子(以及更多测试)后,我最终得到了这个,这似乎有效:

    my %newrow = %{$_TD->{new}};
    my %oldrow = %{$_TD->{old}};

    my $valChanged;
    while (($column,$value) = each %newrow) {

        $valChanged = 0;

        if($newrow{$column} ne $oldrow{$column}) {
            $valChanged = 1;
            elog(NOTICE, "Values in column $column differ.  New: $_TD->{new}{$column}, Old: $_TD->{old}{$column}");
        }   
        elsif(!defined($newrow{$column}) && defined($oldrow{$column})) {
            elog(NOTICE, "New row contains nulled out field");
            $valChanged = 1;
        }
        elsif(defined($newrow{$column}) && !defined($oldrow{$column})) {
            elog(NOTICE, "New row contains newly populated field");
            $valChanged = 1;
        }

        if($valChanged) {
            ### Update audit table
        }
    }
Run Code Online (Sandbox Code Playgroud)

它捕捉空字符串和 NULL 之间的差异,并将它们全部适当地记录在审计表中。

fil*_*rem 4

您没有指定 PostgreSQL 版本。在 9.0.5 上我观察到了相同的行为(不确定这是否是一个错误,请参阅下面的评论)。

这很容易解决 - 您可以首先测试捕获 NULL 的定义,如果通过,则测试空字符串。

if ( not defined $_TD->{ new }{ $column } ) {
    elog( NOTICE, "New value in column $column is not defined" );
}
elsif ( $_TD->{ new }{ $column } eq '' ) {
    elog( NOTICE, "New value in column $column is empty" );
}
if ( not defined $_TD->{ old }{ $column } ) {
    elog( NOTICE, "Old value in column $column is not defined" );
}
elsif ( $_TD->{ old }{ $column } eq '' ) {
    elog( NOTICE, "Old value in column $column is empty" );
}
Run Code Online (Sandbox Code Playgroud)