PostgreSQL PL/Perl Trigger, дифференцируйте NULL против пустого
-
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" );
}