Re: trigger d'historisation

Lists: pgsql-fr-generale
From: "Sihem MOUALHI" <Sihem(dot)MOUALHI(at)cefe(dot)cnrs(dot)fr>
To: <pgsql-fr-generale(at)postgresql(dot)org>
Subject: Re: trigger d'historisation
Date: 2011-04-12 14:37:42
Message-ID: 01B930F7330B8F4590FB58789BE3CED58F12B3@ZZML.newcefe.newage.fr
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-fr-generale

Voici le code du trigger que j'utilise:

CREATE OR REPLACE FUNCTION histo_table() RETURNS TRIGGER AS $histo_table$

BEGIN

IF (TG_OP = 'DELETE') THEN

INSERT INTO history_table (date, attribut2, attribut3,...)

SELECT now(), OLD.attribut2, OLD.attribut3,..

FROM matable;

ELSIF (TG_OP = 'UPDATE') THEN

INSERT INTO history_table (date, attribut2, attribut3,...)

SELECT now(), OLD.attribut2, OLD.attribut3,..

FROM matable;

END IF;

RETURN NULL;

END;

$histo_table$ LANGUAGE plpgsql;

CREATE TRIGGER histo_table

AFTER UPDATE OR DELETE ON matable

FOR EACH ROW EXECUTE PROCEDURE histo_table();

La clé primaire des tables historiques est un serial.

-----Message d'origine-----

De : Guillaume Lelarge [mailto:guillaume(at)lelarge(dot)info]

Envoyé : mardi 12 avril 2011 16:23

À : Sihem MOUALHI

Cc : pgsql-fr-generale(at)postgresql(dot)org

Objet : Re: [pgsql-fr-generale] trigger d'historisation

Bonjour,

Le 12/04/2011 16:02, Sihem MOUALHI a écrit :

> [...]

> J'ai réalisé des tables historiques pour chacune des tables de la base sur laquelle je travaille actuellement et l'historisation se fait via des triggers. Ainsi, lorsqu'on modifie un enregistrement ou qu'on le supprime, celui-ci sera enregistré dans la table historique correspondante. Cependant, lorsqu'on effectue l'opération DELETE sur une table ne contenant qu'une seule ligne (la table sera donc vide), cette ligne n'est pas enregistrée dans la table historique.

>

> Sauriez-vous quelle en est la raison ?

>

Une procédure stockée buggée, une mauvaise déclaration du trigger...

tout est imaginable sans plus d'informations.

Sauf le bug dans PostgreSQL vu que j'ai testé de mon côté et que cela

fonctionne (avec une version 9.0).

--

Guillaume

http://www.postgresql.fr

http://dalibo.com


From: "Daniel Verite" <daniel(at)manitou-mail(dot)org>
To: "Sihem MOUALHI" <Sihem(dot)MOUALHI(at)cefe(dot)cnrs(dot)fr>
Cc: pgsql-fr-generale(at)postgresql(dot)org
Subject: Re: trigger d'historisation
Date: 2011-04-12 14:48:51
Message-ID: Postg롤 토토SQL : 롤 토토 : Trigger d 'Histor
Views: Raw Message | Postg스포츠 토토 베트맨SQL | Download mbox | Resend email
Lists: pgsql-fr-generale

Sihem MOUALHI wrote:

> IF (TG_OP = 'DELETE') THEN
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
>
> ELSIF (TG_OP = 'UPDATE') THEN
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
> END IF;

Ce code insère autant de lignes dans history_table qu'il y a de lignes dans
matable et ce à chaque opération, ce qui n'est pas le but recherché.
Pour corriger le problème, il faut enlever les "FROM matable" des deux INSERT
puisqu'il s'agit d'insérer OLD.* complètement indépendamment ce qu'il y a
dans matable.

Cordialement,
--
Daniel


From: Guillaume Lelarge <guillaume(at)lelarge(dot)info>
To: Sihem MOUALHI <Sihem(dot)MOUALHI(at)cefe(dot)cnrs(dot)fr>
Cc: pgsql-fr-generale(at)postgresql(dot)org
Subject: Re: trigger d'historisation
Date: 2011-04-12 14:53:25
Message-ID: 4DA46765.8010905@lelarge.info
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-fr-generale

Le 12/04/2011 16:37, Sihem MOUALHI a écrit :
> Voici le code du trigger que j'utilise:
>
> CREATE OR REPLACE FUNCTION histo_table() RETURNS TRIGGER AS $histo_table$
>
> BEGIN
>
> IF (TG_OP = 'DELETE') THEN
>
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
>
> ELSIF (TG_OP = 'UPDATE') THEN
>
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
> END IF;
>
> RETURN NULL;
> END;
>

Donc c'est bien une fonction trigger buggée, même si je n'ai pas compris
immédiatement pourquoi :)

Donc, en gros, vous exécutez ceci :

INSERT INTO history_table (date, attribut2, attribut3,...)
SELECT now(), OLD.attribut2, OLD.attribut3,..
FROM matable;

Si vous avez deux lignes dans la table, votre trigger AFTER s'exécute
alors que la ligne est supprimée. Cependant, vous aviez deux lignes, le
SELECT ramène une seule ligne, donc vous avez votre insertion.

Si maintenant vous exécutez un DELETE sur votre table qui ne contient
plus qu'une ligne, le SELECT ramène 0 lignes, d'où pas d'insertion.

Bref, pour corriger votre erreur, supprimer le SELECT. Vous obtiendrez
ceci :

INSERT INTO history_table (date, attribut2, attribut3,...)
VALUES (now(), OLD.attribut2, OLD.attribut3, ...);

--
Guillaume
http://www.postgresql.fr
http://dalibo.com


From: "Sihem MOUALHI" <Sihem(dot)MOUALHI(at)cefe(dot)cnrs(dot)fr>
To: "Guillaume Lelarge" <guillaume(at)lelarge(dot)info>
Cc: <pgsql-fr-generale(at)postgresql(dot)org>
Subject: Re: trigger d'historisation
Date: 2011-04-12 15:02:43
Message-ID: 01B930F7330B8F4590FB58789BE3CED58F12BA@ZZML.newcefe.newage.fr
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: Postg토토 결과SQL : Postg토토

En effet, cela fonctionne.

Merci pour votre aide et vos explications.

Sihem MOUALHI

-----Message d'origine-----
De : Guillaume Lelarge [mailto:guillaume(at)lelarge(dot)info]
Envoyé : mardi 12 avril 2011 16:53
À : Sihem MOUALHI
Cc : pgsql-fr-generale(at)postgresql(dot)org
Objet : Re: [pgsql-fr-generale] trigger d'historisation

Le 12/04/2011 16:37, Sihem MOUALHI a écrit :
> Voici le code du trigger que j'utilise:
>
> CREATE OR REPLACE FUNCTION histo_table() RETURNS TRIGGER AS $histo_table$
>
> BEGIN
>
> IF (TG_OP = 'DELETE') THEN
>
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
>
> ELSIF (TG_OP = 'UPDATE') THEN
>
> INSERT INTO history_table (date, attribut2, attribut3,...)
> SELECT now(), OLD.attribut2, OLD.attribut3,..
> FROM matable;
> END IF;
>
> RETURN NULL;
> END;
>

Donc c'est bien une fonction trigger buggée, même si je n'ai pas compris
immédiatement pourquoi :)

Donc, en gros, vous exécutez ceci :

INSERT INTO history_table (date, attribut2, attribut3,...)
SELECT now(), OLD.attribut2, OLD.attribut3,..
FROM matable;

Si vous avez deux lignes dans la table, votre trigger AFTER s'exécute
alors que la ligne est supprimée. Cependant, vous aviez deux lignes, le
SELECT ramène une seule ligne, donc vous avez votre insertion.

Si maintenant vous exécutez un DELETE sur votre table qui ne contient
plus qu'une ligne, le SELECT ramène 0 lignes, d'où pas d'insertion.

Bref, pour corriger votre erreur, supprimer le SELECT. Vous obtiendrez
ceci :

INSERT INTO history_table (date, attribut2, attribut3,...)
VALUES (now(), OLD.attribut2, OLD.attribut3, ...);

--
Guillaume
http://www.postgresql.fr
http://dalibo.com