Question

J'ai essayé d'accélérer un déclencheur d'audit générique que j'avais écrit en pl / pgsql un peu de temps en arrière. Le jour, il génère une liste de colonnes dans la table étant mise à jour et insère des lignes dans la table de vérification d'enregistrement des modifications (par tableau, la colonne, les données avant les données après, etc.). La même fonction de déclenchement est utilisé sur plusieurs tables.

Je suis jouer avec pl / perl comme il semble être beaucoup plus rapide pour la tâche à accomplir, mais il me semble avoir rencontré un problème sur la différence entre NULL et la valeur chaîne vide ( « ») dans la base de données.

Dans mon esprit, si une colonne passe de NULL à une chaîne vide (ou vice versa), qui est un changement que je dois enregistrer. Cependant, en utilisant les nouvelles disponibles / anciennes références de colonne (_TD $ -> {new / old} {} columnName $), je ne peux pas sembler faire la différence entre les colonnes qui sont réellement nulles et celles qui contiennent la chaîne vide. Les colonnes que je sais sont invalidés sont capturés à la fois par le vide et les contrôles FNUD, comme les colonnes que je connais sont vides.

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

Je pense que je fais quelque chose de stupide ici, mais peut-être que je suis en train de faire quelque chose que je ne peux tout simplement pas faire. Un conseil?

Modifier - Utiliser Postgres 8.4.4 pour ce que ça vaut

Modifier - Après avoir regardé le poste de filiprem ci-dessous (et beaucoup plus de tests), j'ai fini avec ce qui semble fonctionner:

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

Il attrape la différence entre les chaînes vides et les valeurs NULL et les journaux tous correctement dans la table d'audit.

Était-ce utile?

La solution

Vous n'avez pas spécifié la version PostgreSQL. Sur 9.0.5 je l'ai observé le même comportement (pas sûr que ce soit un bug, voir les commentaires ci-dessous).

Ceci est facile à contourner le problème - vous pouvez premier test pour NULL pour attraper définition des modèles, et s'il est passé, test chaîne vide.

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" );
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top