Précédent   Forum du club des développeurs et IT Pro > Bases de données > Firebird
Firebird Forum d'entraide sur le SGBD Firebird. Avant de poster -> F.A.Q Firebird, Tutoriels
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 29/12/2012, 01h19   #1
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Par défaut Problème avec les PS et Triggers

Bonjour tout le monde;
Je n'ai pas compris ce qui se passe!
J'ai un trigger MDF_VEHICULE et je veux le désactiver lors de l'exédution d'une procédure stocké P puis je le réactive à la fin.
Dans le corps de P, j'écris :
Code :
1
2
3
4
5
6
7
8
 
DECLARE VARIABLE STMT VARCHAR(150);
BEGIN
STMT = 'ALTER TRIGGER MDF_VEHICULE INACTIVE'
EXECUTE STATEMENT :STMT;
...
STMT = 'ALTER TRIGGER MDF_VEHICULE ACTIVE'
EXECUTE STATEMENT :STMT;
mais ça ne marche pas, cad que le trigger s'exécute comme si la ligne de désactivation dans P n'existait pas.
mais si j'exécute la requête
Code :
1
2
 
ALTER TRIGGER MDF_VEHICULE INACTIVE
il se désactive.
J'ai essayé de déboguer la procédure stockée dans EMS et je trouve qu'à la ligne : EXECUTE STATEMENT :STMT;
il déclenche une erreur me disant qu'il est impossible de préparer la query car le statement est vide
Code :
1
2
3
 
Can't Prepare , because  query is emptySQL Code: 37
IB Error Number: 0
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 02h27   #2
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Je l'ai trouvé après une nuit blanche
Il suffit de faire suspend après l'exécution du statement; je ne sais pas pourquoi;
Code :
1
2
3
4
5
6
DECLARE VARIABLE STMT VARCHAR(150); 
BEGIN 
STMT = 'ALTER TRIGGER MDF_VEHICULE INACTIVE' ;
EXECUTE STATEMENT :STMT;
SUSPEND;
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 02h36   #3
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
En réalité rien n'est résolut;
Le "suspend" faisait le rôle de "exit" de la procédure stockée sans exécuter les lignes après.
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 08h56   #4
SergioMaster
Modérateur
 
Avatar de SergioMaster
 
Homme Serge Girard
Développeur informatique
Inscription : janvier 2007
Messages : 4 207
Détails du profil
Informations personnelles :
Nom : Homme Serge Girard
Âge : 56
Localisation : France

Informations professionnelles :
Activité : Développeur informatique
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 4 207
Points : 7 265
Points : 7 265
Bonjour , essayez avec COMMIT plutôt que suspend ;

perso , j'ai toujours utiliser la méthode
Code :
1
2
3
4
5
 
Desactiver 
UPDATE RDB$TRIGGERS T SET RDB$TRIGGER_INACTIVE = 1 WHERE  T.RDB$TRIGGER_NAME=NOM_PROCEDURE
Reactiver
UPDATE RDB$TRIGGERS T SET RDB$TRIGGER_INACTIVE = 0 WHERE T.RDB$TRIGGER_NAME=NOM_PROCEDURE
je ne connaissais/me rappelais pas le ACTIVE/INACTIVE , chouette j'ai (ré-)appris quelque-chose , il faut dire que j'utilise rarement le activer/désactiver et dans ce cas c'est généralement pour tous les triggers non système !
Code :
1
2
 
WHERE T.RDB$SYSTEM_FLAG = 0
__________________
La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein
J'entends et j'oublie. Je vois et je me souviens. Je fais et je comprends . Confucius
Si votre seul outil est un marteau, vous aurez tendance a ne voir que des clous
SergioMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 10h05   #5
alanglet
Membre régulier
 
André Langlet
Inscription : avril 2010
Messages : 45
Détails du profil
Informations personnelles :
Nom : André Langlet

Informations forums :
Inscription : avril 2010
Messages : 45
Points : 71
Points : 71
Bonjour,

Il me semble que la méthode consistant à activer/désactiver des triggers de cette façon devrait être réservée à quelques cas particuliers, car elle ne peut être pratiquée que par le SYSDBA ou le propriétaire de la base. De plus elle n'est pas sans danger en environnement multi-utilisateurs.
Quand c'est nécessaire, je préfère utiliser un variable d'environnement par exemple:
Code :
1
2
3
4
SELECT rdb$set_context('USER_TRANSACTION','INACTIVE_TRIGGER','1') FROM rdb$database
pour la positionner, puis
SELECT rdb$set_context('USER_TRANSACTION','INACTIVE_TRIGGER',NULL) FROM rdb$database
pour la supprimer
et dans les triggers concernés, tester l'existence de cette variable avant d'exécuter le code.
L'utilisateur n'a ainsi pas besoin de droits particuliers et lui seul est concerné par cette modification dans l'exécution d'un trigger.

André
alanglet est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 10h53   #6
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Merci Sergio;
Même ta méthode ne marche pas cad :
Code :
1
2
 
UPDATE RDB$TRIGGERS SET RDB$TRIGGER_INACTIVE = 1 WHERE  RDB$TRIGGER_NAME='MDF_VEHICULE';
le trigger fonctionne comme si je n'est rien écris.
Alors pour le commit à la place de suspend le commit est pour les transaction pas pour les procédures.
pour André, je n'ai pas compris comment utiliser les variables, où est ce que je précise le nom du trigger à désactiver?
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 11h04   #7
SergioMaster
Modérateur
 
Avatar de SergioMaster
 
Homme Serge Girard
Développeur informatique
Inscription : janvier 2007
Messages : 4 207
Détails du profil
Informations personnelles :
Nom : Homme Serge Girard
Âge : 56
Localisation : France

Informations professionnelles :
Activité : Développeur informatique
Secteur : Industrie

Informations forums :
Inscription : janvier 2007
Messages : 4 207
Points : 7 265
Points : 7 265
Citation:
Alors pour le commit à la place de suspend le commit est pour les transaction pas pour les procédures
tout à fait , mais une procédure est une transaction en soit,(le UPDATE ou le ALTER devrait être 'Commité' , alors , avant de dire que cela ne fonctionnera pas , il faudrait peut être l'essayer ?

Nota : un SUSPEND est pour renvoyer des résultats

Citation:
Il me semble que la méthode consistant à activer/désactiver des triggers de cette façon devrait être réservée à quelques cas particuliers, car elle ne peut être pratiquée que par le SYSDBA ou le propriétaire de la base. De plus elle n'est pas sans danger en environnement multi-utilisateurs.
absolument
__________________
La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein
J'entends et j'oublie. Je vois et je me souviens. Je fais et je comprends . Confucius
Si votre seul outil est un marteau, vous aurez tendance a ne voir que des clous
SergioMaster est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 11h13   #8
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Citation:
Envoyé par SergioMaster Voir le message
alors , avant de dire que cela ne fonctionnera pas , il faudrait peut être l'essayer ?
absolument
Mais je l'ai essayé avant de le dire
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/12/2012, 14h54   #9
alanglet
Membre régulier
 
André Langlet
Inscription : avril 2010
Messages : 45
Détails du profil
Informations personnelles :
Nom : André Langlet

Informations forums :
Inscription : avril 2010
Messages : 45
Points : 71
Points : 71
Citation:
Envoyé par kaouane Voir le message
pour André, je n'ai pas compris comment utiliser les variables, où est ce que je précise le nom du trigger à désactiver?
1- L'utilisation de rdb$get_context et rdb$set_context est bien expliquée http://www.firebirdsql.org/file/docu...grefupd25.html
2- Ce n'est pas la variable elle même qui active ou désactive un trigger, mais en testant sa valeur ou son existence dans le code du trigger on peut définir quelle partie du code sera ou non exécutée.

André
alanglet est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 30/12/2012, 11h29   #10
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Voila ce que m'a dit l'équipe Firebird :
Citation:
It's not going to work because every DDL (including activating/disactivating indices) is actually executed on commit, so you cannot do it in the middle of transaction. That said, I suppose you could workaround that using an autonomous transaction.;
Cela veut dire que mon idée ne marche pas comme voulu, mais je doit désactiver le trigger et l'activer en dehors de la PS.
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 31/12/2012, 23h25   #11
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Une très bonne solution pour réaliser ce que je voulais faire c'est l'utilisation des variable comme a proposé André (merci pour lui). Au début de la PS j'écris :
Code :
 RDB$SET_CONTEXT(''USER_SESSION'',''PROCEDURE'',1); ....
et à la fin je mais :
Code :
 ... RDB$SET_CONTEXT(''USER_SESSION'',''PROCEDURE'',0);
et dans le trigger je mais :
Code :
 IF (rdb$get_context(''USER_SESSION'', ''PROCEDURE'')=0) THEN     INSERT INTO JOURNAL ("UTILISATEUR","DATE","TIME") ...............
le tigger n'est éxécuté qu'en dehors de la procédure et aussi sans aucune crainte dans un environnement multi utilisateurs. Et ça marche très bien. Merci pour tout le monde et spécialement pour Sergio et André
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/01/2013, 03h34   #12
alanglet
Membre régulier
 
André Langlet
Inscription : avril 2010
Messages : 45
Détails du profil
Informations personnelles :
Nom : André Langlet

Informations forums :
Inscription : avril 2010
Messages : 45
Points : 71
Points : 71
Cà m'étonnerai que çà marche correctement comme cela.
La variable contextuelle est une chaîne de caractères. Tester sur l'existence de la valeur "0" dans le trigger, implique que la procédure ait au moins été exécutée une fois avant pour placer cette valeur.
C'est bien pour çà que dans mes messages précédents, je mets la variable à NULL en fin de procédure, et que je parle de tester "l'existence" dans le trigger.
Il n'est dans ce cas pas indispensable de mettre cette valeur dans le contexte de la session, celui de la transaction est suffisant et plus sûr en cas de problème au cours de l'exécution.
André
alanglet est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 02/01/2013, 15h54   #13
kaouane
Membre habitué
 
Inscription : mai 2006
Messages : 233
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : mai 2006
Messages : 233
Points : 109
Points : 109
Citation:
Envoyé par alanglet Voir le message
Cà m'étonnerai que çà marche correctement comme cela.
Je te rassure que ça marche très bien;
Citation:
Envoyé par alanglet Voir le message
La variable contextuelle est une chaîne de caractères. Tester sur l'existence de la valeur "0" dans le trigger, implique que la procédure ait au moins été exécutée une fois avant pour placer cette valeur.
La valeur de la variable contextuelle n'est pas une chaine de caractère mais de n'importe quelle velaur : http://www.firebirdsql.org/refdocs/l...t-context.html L'enchainement de l'exécution est le suivant :
  1. La PS démarre ;
  2. La valeur de la variable contex est modifié à 1 ;
  3. Les tables concernées par les trigger sont modifiés ;
  4. Les trigger sont déclencher, mais comme la valeur de la variable contex ne vérifie pas la condition du trigger, on sort sans l'exécuter ;
  5. A la fin de la PS la valeur de la var context est remis à la valeur général permettant l'exécution des trigger ;
Et ça marche comme prévu
__________________
Deux personnes n'apprennent pas, un arrogant et un timide.
kaouane est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Cette discussion est résolue.
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 23h52.


 
 
 
 
Partenaires

Hébergement Web