PostgreSQL PL/Perl Trigger, дифференцируйте NULL против пустого

dba.stackexchange https://dba.stackexchange.com/questions/7475

  •  16-10-2019
  •  | 
  •  

Вопрос

Я пытался ускорить общий триггер аудита, который я написал в PL/PGSQL некоторое время назад. При обновлении он генерирует список столбцов в обновленной таблице, и вводит строки в таблицу аудитов, записывая любые изменения (по таблице, столбцы, данные перед, данные после и т. Д.). Одна и та же функция триггера используется в нескольких таблицах.

Я играю с PL/Perl, так как это кажется намного быстрее для поставленной задачи, но я, кажется, столкнулся с проблемой в различие между нулевой и пустой строкой ('') значением в базе данных.

На мой взгляд, если столбец переходит от нуля к пустой строке (или наоборот), это изменение, которое мне нужно записать. Однако, используя доступные новые/старые ссылки на столбцы ($ _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");
    }

Я подозреваю, что я делаю что -то глупое здесь, но, может быть, я пытаюсь сделать то, что просто не могу сделать. Любой совет?

РЕДАКТИРОВАТЬ - Использование Postgres 8.4.4 для того, что стоит

РЕДАКТИРОВАТЬ - После рассмотрения пост Филипрема ниже (и многое другое тестирование), я закончил этим, что, кажется, работает:

    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
        }
    }

Он ловит разницу между пустыми строками и нулю и регистрирует их все соответствующим образом в таблице аудита.

Это было полезно?

Решение

Вы не указали версию PostgreSQL. На 9.0.5 я наблюдал то же поведение (не уверен, что это ошибка, см. Комментарии ниже).

Это легко обходно - вы можете сначала проверить, чтобы определить, чтобы поймать ноль, и, если он пройдет, проверьте на пустую строку.

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" );
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с dba.stackexchange
scroll top