Postgresql

PostgreSQL pl/perl 觸發器,區分 null 與空

  • November 30, 2011

我一直在嘗試加速我以前用 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");
   }

我懷疑我在這裡做了一些愚蠢的事情,但也許我正在嘗試做一些我根本做不到的事情。有什麼建議嗎?

編輯 - 使用 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
       }
   }

它擷取空字元串和 NULL 之間的差異,並將它們都適當地記錄在審計表中。

您沒有指定 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" );
}

引用自:https://dba.stackexchange.com/questions/7475