bon..
j'ai essayé d'adapter tout ça..
je suis sur TOAD en ce moment..
donc les requetes UPDATE je les fais à la main..
si j'ai bien compris, il faut que j'agisse sur la vue pour faire des modifications????
bon..
j'ai essayé d'adapter tout ça..
je suis sur TOAD en ce moment..
donc les requetes UPDATE je les fais à la main..
si j'ai bien compris, il faut que j'agisse sur la vue pour faire des modifications????
le trigger instead of marche très bien..
je modifie les champs dans ma vue..et le résultat est bel et bien dans la table principale (login)
Le problème, c'est que je touche à la base depuis des DLLs..et je peux pas attaquer des vues pour faire des modifications..
Dans ce cas, je ne vois que la dernière méthode proposée dans l'article de Pomalaix qui puisse te convenir :
- tu crées un entête de package avec trois variables (login, code, flag)
- un declencheur before update for each row qui mémorise ton flag et ton login et ton code dans les variables de package
- un déclencheur after update qui met à jour ta table suivant les variables de package mémorisée.
Un problème sans solution est un problème mal posé
Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
Je me perds là
d'abord, dans le before update, il faut que je mémorise quelles variables?? là où le flag est à 1 (donc la seule ligne)
puis dans le after update..j'écris le code que j'avais déja écrit ??
excuse moi mais ça fait un petit moment que je puise dans l'exemple du lien que tu m'as donné..
je te dis franchement.. c'est bp trop compliqué pour moi!
Comme PlaineR :
Je vais développer mon idée des 2 tables :
Table TLOGIN (login, code, flag) PK Login/Code
Table TLOGIN_FLAG (login, code) PK Login
FK de login/code vers TLOGIN (login/code)
Le flag de TLOGIN ne sert qu'à déclencher le trigger, on peut aussi utiliser une variable de session dans un package
Trigger sur TLOGIN UPDATE FOR EACH ROWS
Pour savoir quel login/code est au flag = 1, ce'st celui qui est dans la table TLOGIN_FLAG
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 IF :new.flag = 1 THEN :new.flag := null; -- la colonne ne sert à rien UPDATE TLOGIN_FLAG set code = :new.code WHERE login = :new.login; IF SQL%ROWCOUNT = 0 THEN INSERT INTO TLOGIN_FLAG (login, code) VALUES (:new_login, :new_code); END IF; END IF;
More Code : More Bugs. Less Code : Less Bugs
Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP
mais dans ton script, où est-ce qu'on met la colonne FLAG à 0 pour tous les autres enregistrements??
je précise que ma table principale c'est:
MyTable(Login, Code, Flag)
et que en principe je devrais faire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 For each row... If :New.Flag = 1 THEN UPDATE MyTable SET Flag = 0 where login = :New.Login And code <> :New.Code; END IF;
Tiens, j'ai une idée rigolote pour économiser les packages et/ou tables temporaires.....
je vois le truc en 2 temps
- Dans un trigger before insert/update "for each row" tu capte la modif de flag à 1, et au lieu de mettre 1 tu remplace par 2!
- Dans un trigger after statement insert/update (il suffit de ne pas mettre le "for each row") ta table n'est plus en mutation donc tu peux agir dessus... et là tu commence par chercher et remplacer le 1 par 0, puis le 2 par 1, clic/clac l'affaire est dans le sac
Reste à afiner pour les cas ou on fait une modif de plus d'une ligne à la fois, il faudra choisir arbitrairement, une des lignes qui va rester flaguée à 1 quand toutes les autres seront passeront à 0....
On pourrait aussi envisager de se passer de triggers si on encapsule toutes les écritures (INSERT/UPDATE/DELETE) dans la table en question dans des procédures stockées et si on se pose comme contrainte de ne pas faire d'INSERT/UPDATE/DELETE directement mais de toujours passer par les procédures stockées.
Cette contrainte peut être réalisée en interdisant la connexion dans l'application par le compte propriétaire du schéma et ne donnant que les droits d'exécution sur les procédures à d'autres comptes distincts (en plus du SELECT).
C'est ce que je proposais ici :
Envoyé par nuke_y
Il vaut mieux monopoliser son intelligence sur des bêtises que sa bêtise sur des choses intelligentes.
c'est un peu l'esprit du "instead of" c'est vrai que c'est peut etre mieux d'un point de vue programmation mais la table n'a plus sa consistance propre... tant qu'à passer par des fonctions, à ce moment là, autant le faire directement depuis l'applicatif....
la modification du flag à 1, c'est moi qui la fait!- Dans un trigger before insert/update "for each row" tu capte la modif de flag à 1, et au lieu de mettre 1 tu remplace par 2!
tu me demandes dans un premier temps d'écrire ceci :
ce qui à mon avis n'a pas d'intéret car la table est toujours en mutation..
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 CREATE OR REPLACE TRIGGER TRIGGER_1 BEFORE UPDATE ON MyTable FOR EACH ROW BEGIN IF :New.FLAG =1 then UPDATE MyTable SET FLAG= 2; END IF; END;
donc à mon avis, tu veux dire autre chose que je n'ai pas compris
plutôt :
mutation de table = SELECT, INSERT ou UPDATE sur la table qui déclenche le trigger.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 IF :New.FLAG =1 then :New.FLAG := 2; END IF;
Code du 1er trigger..
Code du 2ème trigger..
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 CREATE OR REPLACE TRIGGER TRIGGER_1 BEFORE UPDATE ON MyTable FOR EACH ROW BEGIN IF :New.Active =1 then :New.Active :=2; END IF; END;
Le premier fonctionne bien..
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
26
27
28
29
30
31 CREATE OR REPLACE TRIGGER TRIGGER_2 AFTER UPDATE ON MyTable DECLARE tmpvar INTEGER; tmpvar2 INTEGER; tmpstr VARCHAR2(50); tmpstr2 VARCHAR2(50); BEGIN Select login, code into tmpvar, tmpstr FROM MyTable where Flag= 1; Select login, code into tmpvar2, tmpstr2 FROM MyTable where Flag= 2; UPDATE MyTable SET Flag= 0 WHERE Login = tmpvar AND Code= tmpstr; UPDATE MyTable SET Flag= 1 WHERE Login = tmpvar2 AND Code= tmpstr2; END ;
J'ai toujours le problème de la table mutante pour le 2ème trigger..
Je dois avoir loopé un truc dans ton idée..
En fait il y a un problème de récursivité chez moi....
Il faut faire gaffe à pas faire des updates en cascades....
Non, ça ne peut pas marcher : ton trigger after update va redéclencher ton trigger for each row et soit cela va boucler, soit tu vas te retrouver avec un flag égal à 2.Envoyé par remi4444
[EDIT] Excuse je n'avais pas vu ton dernier post [/EDIT]
Un problème sans solution est un problème mal posé
Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
Oui c'était le soucis, j'avais pas fait gaffe que meme quand l'update se fait sur 0 ligne, le trigger "after statement" se déclenche quand meme
Mais je crois que j'ai trouvé:
Un problème digne des meilleures écoles d'informatique...
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 CREATE TABLE TOTO (LOGIN varchar2(50),CODE varchar2(50),FLAG NUMBER(1) default 0); CREATE OR REPLACE TRIGGER TRG_TOTO_BIU_ROW BEFORE INSERT OR UPDATE ON TOTO FOR EACH ROW BEGIN -- test si il y a un changement de flag vers la valeur 1 -- dans ce cas on le passe à 2 pour signaler que c'est une nouvelle valeur --return; IF :new.FLAG = 1 and (INSERTING OR (UPDATING AND nvl(:old.FLAG,0) != 1 AND nvl(:old.FLAG,0) != 2 /*pour pas tourner en rond */ ) ) then :new.FLAG := 2; end if; END ; / CREATE OR REPLACE TRIGGER TRG_TOTO_AIU_STATEMENT AFTER INSERT OR UPDATE ON TOTO DECLARE l_login TOTO.LOGIN%TYPE; l_code TOTO.CODE%TYPE; BEGIN -- apres le statement, la table n'est plus en mutation, on peut donc agir dessus. -- recherche d'une ligne flaguée à 2 select CODE,LOGIN into l_code,l_login from TOTO where FLAG = 2 and rownum = 1; -- FLAG 1 sur la ligne modifiée -- il faut d'abord faire cette modif sinon ça tourne en rond.... update TOTO set FLAG = 1 where CODE = l_code and LOGIN = l_login; -- FLAG 0 sur toutes les autres lignes update TOTO set FLAG = 0 where FLAG in (1,2) and (CODE != l_code or LOGIN != l_login); EXCEPTION WHEN NO_DATA_FOUND THEN -- pas d'action si il n'y a pas de 2 null; END ; /
Chapeau Remi...
ça marche à merveille..
Il faut vraiment le marquer ce post là, parce que il n'existe nulle part..
Parfois, il suffit d'une petite bidouille pour contourner des problèmes de création de tables suppémentaires ou je ne sais quoi d'autres..
Merci à tout le monde d'avoir échangé ces quelques propos très intéressants..
Salut
Le trigger suivant qui en cencé générer un message d'erreur est accepté mais avec des erreurs de compilation je ne comprends pas du tout pourquoi est ce que qlq un a une idée?
merci d'avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 CREATE OR REPLACE TRIGGER tg_integrite BEFORE INSERT OR UPDATE ON VOYAGES FOR EACH ROW BEGIN IF :NEW.id_client NOT IN (SELECT NUM_client FROM CLIENTS, VOYAGES WHERE CLIENTS.NUM_CLIENT = VOYAGES.:NEW.id_client) THEN RAISE_APPLICATION_ERROR(-20001,'Le client n''existe pas'); END IF; END tg_integrite;
recherche table mutante ou mutating table. Tu n'as pas le droit de sélectionner la table qui porte le trigger
Enléve VOYAGES du SELECT et ça ira beaucoup mieux
helas tjs meme erreur de compilation mais trigger créé.
Je sèche complètement
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 CREATE OR REPLACE TRIGGER tg_integrite BEFORE INSERT OR UPDATE ON VOYAGES FOR EACH ROW BEGIN IF :NEW.id_client not in (SELECT NUM_client FROM CLIENTS); THEN RAISE_APPLICATION_ERROR(-20001,'Le client n'existe pas'); END IF; END tg_integrite;
S.o.S
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager