banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

GEODATA DAYS 2024

#1 Mon 17 January 2011 15:56

renard
Participant actif
Date d'inscription: 16 Mar 2010
Messages: 96

Trigger pour vider une table avant insertion

Bonjour,

Je souhaiterais que lors du premier INSERT ou UPDATE de ma table 'test_trigger', le contenu de celle-ci soit effacé.

Je m'explique sur l'illogisme de ce trigger. J'utilise geoconcept  qui exporte les données vers une base postgresql/postgis de sorte que ces données exportées puissent être utiliser dans une autre application.
Cependant Geoconcept agit avec postgresl que par insert ou update (puisque je ne l'utilise qu'en export et non en liens permanents, je ne souhaite pas migrer ma base de données vers postgis mais simplement une partie de celles-ci pour être utilisé avec mapserver).

Ce qui me pose le problème suivant :lorsque je supprime une donnée de geoconcept, celle-ci n'est pas supprimé dans la base postgresl (puisqu'il n'y a que des insertion et des mises à jour mais il ne supprime rien de la base).

Afin de pallier à ce problème, je souhaitais vider ma table avant le premier INSERT ou UPDATE pour que Geoconcept n'ait qu'à insérer l'ensemble des données.

Pour cela j'ai crée le trigger suivant

Code:

CREATE FUNCTION vider_table() RETURNS TRIGGER AS $suppression$
BEGIN 
   TRUNCATE TABLE test_trigger;
END;
$suppression$ language plpgsql;

CREATE TRIGGER suppression 
BEFORE INSERT or UPDATE or DELETE
    ON test_trigger 
    FOR EACH STATEMENT 
    EXECUTE PROCEDURE vider_table();

mais il me renvoie l'erreur suivante aprés un 'insert into'  (testé en requête SQL directement, sans utiliser geoconcept)

Code:

ERROR:  cannot TRUNCATE "test_trigger" because it is being used by active queries in this session
CONTEXT:  SQL statement "TRUNCATE TABLE test_trigger"
PL/pgSQL function "vider_table" line 2 at SQL statement

Que pensez-vous de ma logique? Voyez-vous une autre solution qu'un trigger, ou celui est-il à paramétrer différemment?

Une alternative pourrais être de planifier la tâche d'effacement des lignes de ma table (la mise à jour sera peut fréquente) puis planifier l'export de Géoconcept. Cependant je ne trouve pas d'information quant à la planification avec postgresql. Sinon n'y a t-il pas de possibilités de créer un batch, si oui, comment "charger" l'environnement PSQL (je suis sous windows).

Par avance merci,

Hors ligne

 

#2 Mon 17 January 2011 16:02

Yves
Membre du bureau
Lieu: Aix-les-Bains
Date d'inscription: 22 Mar 2006
Messages: 9863
Site web

Re: Trigger pour vider une table avant insertion

Bonjour,

Le trigger est relancé à chaque suppression de ligne non ?

Pourquoi créer une fonction ? Pourquoi ne pas mettre le TRUNCATE ... dans le trigger ?

Y.


Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !!  - GeoRezo vous aide ? Aidez GeoRezo !

Hors ligne

 

#3 Mon 17 January 2011 16:30

renard
Participant actif
Date d'inscription: 16 Mar 2010
Messages: 96

Re: Trigger pour vider une table avant insertion

J'ai crée une fonction car la doc indique

Code:

    CREATE TRIGGER nom { BEFORE | AFTER } { evenement [ OR ... ] }
    ON table [ FOR [ EACH ] { ROW | STATEMENT } ]
    [ WHEN ( condition ) ]
    EXECUTE PROCEDURE nom_fonction ( arguments )

et je n'ai pas réussi à créer un trigger sans utiliser de fonctions, en intégrant le TRUNCATE à la fonction. J'ai aussi essayé avec DELETE FROM, mais rien n'y a fait et effectivement la fonction semble s'exécuter à chaque insertion.

J'ai finalement réussi à vider la table avec un batch (ce qui ne sera pas trop dérangeant en prod dans mon cas)  mais j'aurai préféré réussir avec un déclencheur.

Dernière modification par renard (Mon 17 January 2011 17:02)

Hors ligne

 

#4 Mon 17 January 2011 16:50

Yves
Membre du bureau
Lieu: Aix-les-Bains
Date d'inscription: 22 Mar 2006
Messages: 9863
Site web

Re: Trigger pour vider une table avant insertion

Bonjour,

Déjà tu peux supprimer l'événement DELETE non ?

Y.


Yves Jacolin, bénévole de l'association GeoRezo.net, agit au nom et pour le compte de l'association - Partageons ce qui nous départage !!  - GeoRezo vous aide ? Aidez GeoRezo !

Hors ligne

 

#5 Mon 17 January 2011 17:19

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1538

Re: Trigger pour vider une table avant insertion

renard a écrit:

Bonjour,

Je souhaiterais que lors du premier INSERT ou UPDATE de ma table 'test_trigger', le contenu de celle-ci soit effacé.

Je m'explique sur l'illogisme de ce trigger. J'utilise geoconcept  qui exporte les données vers une base postgresql/postgis de sorte que ces données exportées puissent être utiliser dans une autre application.
Cependant Geoconcept agit avec postgresl que par insert ou update (puisque je ne l'utilise qu'en export et non en liens permanents, je ne souhaite pas migrer ma base de données vers postgis mais simplement une partie de celles-ci pour être utilisé avec mapserver).

Ce qui me pose le problème suivant :lorsque je supprime une donnée de geoconcept, celle-ci n'est pas supprimé dans la base postgresl (puisqu'il n'y a que des insertion et des mises à jour mais il ne supprime rien de la base).

Afin de pallier à ce problème, je souhaitais vider ma table avant le premier INSERT ou UPDATE pour que Geoconcept n'ait qu'à insérer l'ensemble des données.

Pour cela j'ai crée le trigger suivant

Code:

CREATE FUNCTION vider_table() RETURNS TRIGGER AS $suppression$
BEGIN 
   TRUNCATE TABLE test_trigger;
END;
$suppression$ language plpgsql;

CREATE TRIGGER suppression 
BEFORE INSERT or UPDATE or DELETE
    ON test_trigger 
    FOR EACH STATEMENT 
    EXECUTE PROCEDURE vider_table();

mais il me renvoie l'erreur suivante aprés un 'insert into'  (testé en requête SQL directement, sans utiliser geoconcept)

Code:

ERROR:  cannot TRUNCATE "test_trigger" because it is being used by active queries in this session
CONTEXT:  SQL statement "TRUNCATE TABLE test_trigger"
PL/pgSQL function "vider_table" line 2 at SQL statement

Que pensez-vous de ma logique? Voyez-vous une autre solution qu'un trigger, ou celui est-il à paramétrer différemment?

Une alternative pourrais être de planifier la tâche d'effacement des lignes de ma table (la mise à jour sera peut fréquente) puis planifier l'export de Géoconcept. Cependant je ne trouve pas d'information quant à la planification avec postgresql. Sinon n'y a t-il pas de possibilités de créer un batch, si oui, comment "charger" l'environnement PSQL (je suis sous windows).

Par avance merci,


Bonjour,
Un trigger etant executé a chaque fois que la condition est remplie, le truncate va etre executé a chaque fois => une seule ligne possible dans la table (et pas de mise a jour possible, car vidage de la table avant le UPDATE)

D'autre part, je pense que l'operation de DELETE ou TRUNCATE necessite un lock sur la table, qui n'est pas compatible avec la requete en cours, d'ou le message d'erreur.

Effectivement, un batch ou autre forme de programme qui, en premier, met la table dans le bon etat (delete) puis ensuite travaille dessus me semble plus clair.

Nico

Hors ligne

 

#6 Mon 17 January 2011 17:44

renard
Participant actif
Date d'inscription: 16 Mar 2010
Messages: 96

Re: Trigger pour vider une table avant insertion

Merci nicolas pour ces informations.

Je pensais avoir saisi la notion de triggers notamment de "each row statement " pour lequel la doc indique

Code:

Un déclencheur marqué FOR EACH ROW est appelé pour chaque ligne que l'opération modifie. Par exemple, un DELETE affectant
dix lignes entraîne dix appels distincts de tout déclencheur ON DELETE sur la relation cible, une fois par ligne supprimée. Au
contraire, un déclencheur marqué FOR EACH STATEMENT ne s'exécute qu'une fois pour une opération donnée, quelque soit le
nombre de lignes modifiées (en particulier, une opération qui ne modifie aucune ligne résulte toujours en l'exécution des déclencheurs
FOR EACH STATEMENT applicables).

Je pensais ainsi que mon TRUNCATE se ferait avant la première insertion mais effectivement mon trigger semble boucler même lorsque je n'insère qu'une seule ligne. De plus je ne comprends pas ce que retourne le "RETURNS TRIGGER AS".


Je vais donc continuer à travailler  avec un batch.

Une nouvelle fois merci pour l'aide apporté par la communauté Georezo.

Dernière modification par renard (Mon 17 January 2011 17:55)

Hors ligne

 

#7 Mon 17 January 2011 18:14

Nicolas Ribot
Membre
Lieu: Toulouse
Date d'inscription: 9 Sep 2005
Messages: 1538

Re: Trigger pour vider une table avant insertion

renard a écrit:

Merci nicolas pour ces informations.

Je pensais avoir saisi la notion de triggers notamment de "each row statement " pour lequel la doc indique

Code:

Un déclencheur marqué FOR EACH ROW est appelé pour chaque ligne que l'opération modifie. Par exemple, un DELETE affectant
dix lignes entraîne dix appels distincts de tout déclencheur ON DELETE sur la relation cible, une fois par ligne supprimée. Au
contraire, un déclencheur marqué FOR EACH STATEMENT ne s'exécute qu'une fois pour une opération donnée, quelque soit le
nombre de lignes modifiées (en particulier, une opération qui ne modifie aucune ligne résulte toujours en l'exécution des déclencheurs
FOR EACH STATEMENT applicables).

Je pensais ainsi que mon TRUNCATE se ferait avant la première insertion mais effectivement mon trigger semble boucler même lorsque je n'insère qu'une seule ligne. De plus je ne comprends pas ce que retourne le "RETURNS TRIGGER AS".


Je vais donc continuer à travailler  avec un batch.

Une nouvelle fois merci pour l'aide apporté par la communauté Georezo.


Oui pardon, je n'avais pas vu le "for each statement" dans la def de ton trigger.
Le message d'erreur doit etre du au lock sur la table.
(Je vois aussi dans la doc que la fonction du trigger doit forcement renvoyer null dans ton cas. As-tu essayé de forcer cette valeur ?)

Hors ligne

 

Pied de page des forums

Powered by FluxBB