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

Administration Oracle Discussion :

creation de trigger


Sujet :

Administration Oracle

  1. #21
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    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????

  2. #22
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    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..

  3. #23
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    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.

  4. #24
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    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!

  5. #25
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    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
    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;
    Pour savoir quel login/code est au flag = 1, ce'st celui qui est dans la table TLOGIN_FLAG
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  6. #26
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    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;

  7. #27
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut idée...
    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....

  8. #28
    Membre expert

    Profil pro
    Inscrit en
    Février 2006
    Messages
    3 437
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 3 437
    Points : 3 597
    Points
    3 597
    Par défaut Sans trigger
    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).

  9. #29
    Membre émérite Avatar de nuke_y
    Profil pro
    Indépendant en analyse de données
    Inscrit en
    Mai 2004
    Messages
    2 076
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Indépendant en analyse de données

    Informations forums :
    Inscription : Mai 2004
    Messages : 2 076
    Points : 2 370
    Points
    2 370
    Par défaut
    C'est ce que je proposais ici :
    Citation Envoyé par nuke_y
    Ou modifier la façon dont les données sont insérées ? Au lieu d'un INSERT ou UPDATE tout bête tu peux imaginer de créer des fonctions spécifiques à ces tables qui, respectivement, insère la nouvelles ligne PUIS update les autres lignes et update la nouvelles valeur PUIS update les autres lignes.
    Il vaut mieux monopoliser son intelligence sur des bêtises que sa bêtise sur des choses intelligentes.

  10. #30
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    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....

  11. #31
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    - 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!
    la modification du flag à 1, c'est moi qui la fait!
    tu me demandes dans un premier temps d'écrire ceci :
    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;
    ce qui à mon avis n'a pas d'intéret car la table est toujours en mutation..

    donc à mon avis, tu veux dire autre chose que je n'ai pas compris

  12. #32
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    plutôt :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    	   IF :New.FLAG =1 then 
    	  :New.FLAG := 2;
     
    	   END IF;
    mutation de table = SELECT, INSERT ou UPDATE sur la table qui déclenche le trigger.

  13. #33
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    Code du 1er 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;
    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
    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 ;
    Le premier fonctionne bien..
    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..

  14. #34
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    En fait il y a un problème de récursivité chez moi....

    Il faut faire gaffe à pas faire des updates en cascades....

  15. #35
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par remi4444
    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
    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.

    [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.

  16. #36
    Membre éprouvé
    Inscrit en
    Avril 2006
    Messages
    1 024
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 1 024
    Points : 1 294
    Points
    1 294
    Par défaut
    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é:

    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 ;
    /
    Un problème digne des meilleures écoles d'informatique...

  17. #37
    Membre régulier
    Inscrit en
    Septembre 2006
    Messages
    365
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 365
    Points : 83
    Points
    83
    Par défaut
    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..


  18. #38
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 9
    Points : 11
    Points
    11
    Par défaut
    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?

    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;
    merci d'avance

  19. #39
    Expert éminent sénior
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Points : 19 073
    Points
    19 073
    Par défaut
    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

  20. #40
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2006
    Messages : 9
    Points : 11
    Points
    11
    Par défaut
    helas tjs meme erreur de compilation mais trigger créé.


    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;
    Je sèche complètement

    S.o.S

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. [oracle][php]creation de trigger
    Par guittonews dans le forum PL/SQL
    Réponses: 6
    Dernier message: 06/12/2007, 11h10
  2. Probleme de creation de trigger
    Par Cartman.inc dans le forum PL/SQL
    Réponses: 1
    Dernier message: 20/06/2007, 11h11
  3. [PHP5.2][MySQL5.0.27] Creation de triggers depuis PHP
    Par frochard dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 05/12/2006, 10h16
  4. [PL/SQL] Creation de triggers dans transaction
    Par globeriding dans le forum Oracle
    Réponses: 15
    Dernier message: 07/02/2006, 11h33
  5. creation de trigger
    Par mitsubi dans le forum SQL
    Réponses: 3
    Dernier message: 12/09/2003, 15h13

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