IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PostgreSQL Discussion :

trigger historisation des modifications sur une base de données


Sujet :

PostgreSQL

  1. #1
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut trigger historisation des modifications sur une base de données
    Bonjour,
    Je souhaiterai mettre en place un trigger qui insert des lignes dans une table d'historique dès qu'un utilisateur fait des modifications sur la base.

    J'aimerai pouvoir récupère le nom de la table modifié, l'identifiant de la ligne, l'utilisateur qui a fait cette modification, quel est le type de la modification (update,delete,insert), et la date.
    Pour le moment, je n'ai que la date que je sais comment récupère mais le reste je ne sais pas.

    Est ce possible de récupère ces informations?

    Merci d'avance pour tout informations.

  2. #2
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Qu'entends-tu par "l'identifiant de la ligne" ? Car par défaut, une ligne de table n'a pas spécialement d'identifiant unique stable. A moins que les tables soient déclarées WITH OIDS mais cet usage est en voie d'obsolescence.

  3. #3
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Pour les autres données, l'utilisateur s'obtient par la fonction current_user, le nom de la table en argument du trigger avec TG_ARGV, et le nom de l'opération avec TG_OP.

  4. #4
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    Bonjour,
    je te remercie de tes réponses.
    "Qu'entends-tu par "l'identifiant de la ligne" ?" enfaite je parle de la clé primaire de l'enregistrement qui a été modifié.

  5. #5
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    De plus, j'aimerai savoir si c'est possible d'utiliser le même trigger et fonction pour 10 tables différentes?

    pour faire le trigger je me vais m'appuyer sur cette exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$
    BEGIN
        --
        -- Ajoute une ligne dans emp_audit pour refléter l'opération réalisée
        -- sur emp,
        -- utilise la variable spéciale TG_OP pour cette opération.
        --
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*;
            RETURN OLD;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*;
            RETURN NEW;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*;
            RETURN NEW;
        END IF;
        RETURN NULL; -- le résultat est ignoré car il s'agit d'un déclencheur AFTER
    END;
    $emp_audit$ language plpgsql;
     
    CREATE TRIGGER emp_audit
        AFTER INSERT OR UPDATE OR DELETE ON emp
        FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
    et donc ma question est ce possible de mettre sur cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AFTER INSERT OR UPDATE OR DELETE ON emp
    une autre table
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AFTER INSERT OR UPDATE OR DELETE ON emp on salarie on ...
    et donc la j'utiliserai TG_ARVG pour connaitre quelle la table en question.

    je sais pas si c'est bien clair.

  6. #6
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Non un même trigger ne peut pas être associé à plusieurs tables, mais une même fonction peut être associée à plusieurs triggers.

    La difficulté principale pour étendre l'exemple montré à de multiples tables est qu'il déverse dans une unique table d'audit dont la structure est spécifiquement liée à une seule table.

    Pour pouvoir insérer dans une table d'audit déterminée dynamiquement il faut utiliser du SQL dynamique avec EXECUTE et le code va être un niveau de difficulté au-dessus.

    Pour la clef primaire, il faut voir qu'il n'y a pas d'obligation pour une table d'avoir une clef primaire, et que si elle en a une, une clef primaire peut porter sur de multiples colonnes.

  7. #7
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    D'accord merci pour ces informations.
    " mais une même fonction peut être associée à plusieurs triggers." comment une fonction peut être associé a plusieurs trigger étant donnée que dans l'entête on spécifie le nom du trigger?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    create function histo_audit() returns trigger as $histo$
    est ce qu'avec ceux ci TG_Relid je pourrais connaitre correctement l'enregistrement modifié?

  8. #8
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par chris0938 Voir le message
    D'accord merci pour ces informations.
    " mais une même fonction peut être associée à plusieurs triggers." comment une fonction peut être associé a plusieurs trigger étant donnée que dans l'entête on spécifie le nom du trigger?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    create function histo_audit() returns trigger as $histo$
    Non, le nom du trigger n'est pas là, il est dans l'ordre CREATE TRIGGER nom_du_trigger ....

    est ce qu'avec ceux ci TG_Relid je pourrais connaitre correctement l'enregistrement modifié?
    TG_relid permet seulement de connaître la table modifiée. A ce propos je réalise qu'il y a TG_TABLE_NAME et TG_TABLE_SCHEMA comme variables accessibles dans un trigger, donc il vaut mieux utiliser ça plutôt que le mettre soi-même dans TG_ARGV contrairement à ce que je proposais plus haut dans la discussion.

  9. #9
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    Quand on dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    returns TRIGGER AS $histo$
    cela veut bien dire retourné le trigger histo? ou j'ai vraiment mal compris

    TG_RELID l'ID de l'objet de la table qui a causé le déclenchement.
    TG_RELNAME Type de données nom ; le nom de la table qui a causé le déclenchement.

  10. #10
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par chris0938 Voir le message
    cela veut bien dire retourné le trigger histo? ou j'ai vraiment mal compris
    Non ça veut dire totalement autre chose. $histo$ est une balise syntaxique qui encadre le code qui suit juste après. La valeur pourrait aussi bien être $toto$ ou encore $$, tant que cette valeur ne se trouve pas aussi dans le code lui-même, puisqu'elle sert justement à le délimiter.

  11. #11
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    ok merci pour ces informations.
    je vais tester tout cela.

  12. #12
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    Bonjour,
    j'ai mis en place le trigger. j'utilise tg_relname car la version de postgres est la 8.4 donc tg_table_name ne fonctionne pas.
    après cette modification le trigger marche dés que je fais un insert,update..
    mais la seule chose qui ne fonctionne pas c'est l'id de l'enregistrement modifié.
    je m'explique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    insert into profil (id,libelle,datecreation) values ('PROF649302','gestionnaire de site',now());
    INSERT 0 1
     
     
    select * from histo;
        id    | typemod | datemodif    | usermodif | idmodif | tablemodif
    ---------+-----------+---------------+------------+---------+------------
     histo453 | I            | 2011-02-07  | postgres  | 152476  | profil
    idmodif vaut 152476 alors que je voudrai que ca soit prof649302. je ne sais pas si c'est bien possible.

    voici la partie de la fonction qui nous intéresse ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    elsif (TG_OP='INSERT') then
     insert into histo(typemod,datemodif,usermodif,idmodif,tablemodif) select 'I',now(),user,TG_Relid,TG_RELNAME;
    			return new;
    merci d'avance pour toutes idées.

  13. #13
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    je viens de trouver.
    je dois utiliser new.id ou old.id.

    merci

  14. #14
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    Citation Envoyé par chris0938 Voir le message
    j'utilise tg_relname car la version de postgres est la 8.4 donc tg_table_name ne fonctionne pas.
    Ce n'est pas normal car c'est bien disponible en 8.4

  15. #15
    Membre habitué
    Femme Profil pro
    Développeur Web
    Inscrit en
    Mai 2010
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Mai 2010
    Messages : 245
    Points : 164
    Points
    164
    Par défaut
    Bonjour,
    je sais pas. j'ai eu ce message quand j'utilisais tg_table_name:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Error: column "tg_table_name" does not exist
    mais avec tg_relname cela fonctionne donc bon moi ca me va. c'est peut pas aussi bien que tg_table_name mais bon.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 0
    Dernier message: 16/05/2011, 09h52
  2. Réponses: 1
    Dernier message: 02/02/2011, 15h11
  3. audit des connexions sur une base de données
    Par Invité dans le forum Administration
    Réponses: 16
    Dernier message: 28/04/2010, 18h17
  4. Réponses: 7
    Dernier message: 20/08/2009, 18h00
  5. Détecter les modifications sur une base de données
    Par abdelhamidem dans le forum Débuter
    Réponses: 7
    Dernier message: 09/02/2009, 18h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo