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

PL/SQL Oracle Discussion :

Trigger et table en Mutation


Sujet :

PL/SQL Oracle

  1. #1
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut Trigger et table en Mutation
    Bonjour à vous avec mon trigger je voudrais que l’insertion d’une nouvelle opération concerner calcule le nouveau solde du compte en se basant sur le montant de l’opération et je voudrais aussi laisser les traces pour chaque opération effectué par l employé voici un début de code
    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
     
    create or replace TRIGGER DECLANCHE
     
    BEFORE UPDATE ON compte
    FOR EACH ROW
     
    DECLARE
    mttop  operation.mtt_op%type;
     
    BEGIN
    SELECT mtt_op into mttop from OPERATION where num_op = num_op;
     
     
    if mttop > 0 THEN
         UPDATE COMPTE set avoir_cpt = solde_cpt + (   SELECT  mtt_op   FROM    operation  )
    WHERE num_cpt = :new.num_cpt  ;
    else
    UPDATE COMPTE set avoir_cpt = solde_cpt - (   SELECT  mtt_op   FROM    operation  )
    WHERE num_cpt = :new.num_cpt ;
    End if ;
     
     
    EXCEPTION
    		WHEN NO_DATA_FOUND THEN 
    				    raise_application_error(-2001, 'numero de compte non valide non valide');
     
     
     
    END;
    voici mes tables
    Agence (code_ag, nom_ag, ville_ag, #mat_emp) ;
    Employe (mat_emp, nom_emp, date_embauche, numtel_emp, mt_salaire_emp, #code_ag, #code_ag_dir)
    Client (code_cli, nom_cli, numtel_cli)
    Operation (num_op, lib_op, date_op, mtt_op, #mat_emp)
    Compte ( num_cpt, nature_cpt, solde_cpt, avoir_cpt, #code_ag, #mat_emp)
    Concerner (#num_op, #num_cpt, sens)

  2. #2
    McM
    McM est déconnecté
    Expert confirmé

    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
    Billets dans le blog
    4

  3. #3
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut
    Ok j ai vu le post cela ma permis de cerner la chose et par ailleurs j ai modifié mon code ,mais j ai un problème de mutation mais je vois pas comment le relever//
    voici mon code 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
     
    create or replace TRIGGER DECLANCHE
     
    AFTER INSERT ON CONCERNER
    FOR EACH ROW
     
    DECLARE
    mttop  operation.mtt_op%type;
    sensop concerner.sens%type;
    BEGIN
      select sens into sensop from concerner where SENS =SENS;
     
    IF sensop = 1 THEN
         UPDATE COMPTE set avoir_cpt = solde_cpt + (   SELECT  mtt_op   FROM    operation  )
    WHERE num_cpt = :new.num_cpt  ;
    ELSIF  sensop = 2 THEN
    UPDATE COMPTE set avoir_cpt = solde_cpt - (   SELECT  mtt_op   FROM    operation  )
    WHERE num_cpt = :new.num_cpt ;
    End if ;
     
     
    EXCEPTION
    		WHEN NO_DATA_FOUND THEN 
    				    raise_application_error(-2001, 'numero du compte  non valide');
     
     
     
    END;
    quand j insère la donnée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      INSERT INTO CONCERNER (num_op, num_cpt, sens ) VALUES (5, '0084', 2);
    j obtiens cet erreur
    Erreur commençant à la ligne: 1 de la commande -
    INSERT INTO CONCERNER (num_op, num_cpt, sens ) VALUES (5, '0084', 3)
    Rapport d'erreur -
    Erreur SQL : ORA-04091: table NGUIMBIS1.CONCERNER is mutating, trigger/function may not see it
    ORA-06512: at "NGUIMBIS1.DECLANCHE", line 5
    ORA-04088: error during execution of trigger 'NGUIMBIS1.DECLANCHE'
    04091. 00000 - "table %s.%s is mutating, trigger/function may not see it"
    *Cause: A trigger (or a user defined plsql function that is referenced in
    this statement) attempted to look at (or modify) a table that was
    in the middle of being modified by the statement which fired it.
    *Action: Rewrite the trigger (or function) so it does not read that table.

  4. #4
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut Problème dans mon Trigger
    je crois avoir résolu le problème de Trigger jai juste remplacé le
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     select sens into sensop from concerner where SENS =SENS;
    par mais j ai un autre message d erreur provenant du Trigger
    Erreur commençant à la ligne: 1 de la commande -
    INSERT INTO CONCERNER (num_op, num_cpt, sens) VALUES (5, '0084', 1)
    Rapport d'erreur -
    Erreur SQL : ORA-01427: single-row subquery returns more than one row
    ORA-06512: at "NGUIMBIS1.DECLANCHE", line 8
    ORA-04088: error during execution of trigger 'NGUIMBIS1.DECLANCHE'
    01427. 00000 - "single-row subquery returns more than one row"
    *Cause:
    *Action:

  5. #5
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 136
    Par défaut
    La réponse est dans le message d'erreur...
    Combien de lignes retourne ta sous-requête SELECT mtt_op FROM operation ?
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  6. #6
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut
    ok j ai pu remédier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     SELECT  mtt_op   FROM    operation P WHERE P.NUM_OP= :new.NUM_OP
    ca marche mon problème est resolu

  7. #7
    McM
    McM est déconnecté
    Expert confirmé

    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
    Billets dans le blog
    4
    Par défaut
    Tu peux poster ton trigger parce que ce code n'est pas correct
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select sens into sensop from concerner where SENS =SENS;

  8. #8
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut
    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
     
    create or replace TRIGGER DECLANCHE
     
    AFTER INSERT ON CONCERNER
    FOR EACH ROW
     
    DECLARE
    mttop  operation.mtt_op%type;
    sensop concerner.sens%type;
    BEGIN
       sensop:= :new.sens; 
     
    IF sensop = 1 THEN
         UPDATE COMPTE set avoir_cpt = solde_cpt + (   SELECT  mtt_op   FROM    operation P WHERE P.NUM_OP= :new.NUM_OP  )
    WHERE num_cpt = :new.num_cpt  ;
         UPDATE COMPTE set  solde_cpt = avoir_cpt WHERE num_cpt = :new.num_cpt;
     
    ELSIF  sensop = 2 THEN
    UPDATE COMPTE set avoir_cpt = solde_cpt - (   SELECT  mtt_op   FROM    operation P WHERE P.NUM_OP= :new.NUM_OP   )
    WHERE num_cpt = :new.num_cpt ;
    UPDATE COMPTE set  solde_cpt = avoir_cpt WHERE num_cpt = :new.num_cpt;
    End if ;
     
    EXCEPTION
    		WHEN NO_DATA_FOUND THEN 
    				    raise_application_error(-2001, 'numero de compte non valide');
     
     
     
    END;
    Mon problème ici est la gestion des exception en principe je devrais avoir la possibilité de faire uniquement deux choix (sens=1 ou sens=2) à sens=3 aucune erreur ne surviens en plus je sais pas pourquoi mon SET SERVEROUTPUT ON génère une erreur je parviens pas à la mettre dans mon Trigger

  9. #9
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2015
    Messages
    102
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2015
    Messages : 102
    Par défaut
    Citation Envoyé par McM Voir le message
    Tu peux poster ton trigger parce que ce code n'est pas correct
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select sens into sensop from concerner where SENS =SENS;
    j ai modifié le code ...

  10. #10
    McM
    McM est déconnecté
    Expert confirmé

    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
    Billets dans le blog
    4
    Par défaut
    1/ Si tu veux bloquer si le sens n'est pas 1 ou 2, soit tu crées une contrainte CHECK sur la colonne, soit tu le gères à la main dans le trigger avec un test et un raise_application_error

    2/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    RAISE_APPLICATION_ERROR(-2001, 'numero de compte non valide');
    RAISE application_error doit avoir un code > -20000, donc pas -2001, mais -20001
    Sinon erreur
    ORA-21000: error number argument to raise_application_error of -2001 is out of range
    L'exception NO_DATA_FOUND n'est levée que sur un SELECT qui ne ramène aucune donnée.
    Pas sur un Update. A aucun moment il n'y a un test d'existence de compte par un select, donc ce code ne sert à rien.
    Si tu veux tester, soit tu testes que ton update modifie au moins une ligne (IF SQL%ROWCOUNT = 0 THEN RAISE_APPLICATION_ERROR...)
    Soit tu fais un SELECT sur ta table de compte.

    3/
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    UPDATE COMPTE set avoir_cpt = solde_cpt + (   SELECT  mtt_op   FROM    operation P WHERE P.NUM_OP= :NEW.NUM_OP  ) WHERE num_cpt = :NEW.num_cpt  ;
        UPDATE COMPTE set  solde_cpt = avoir_cpt WHERE num_cpt = :NEW.num_cpt;
    2 updates : pas top.
    Attention : Si la table operation n'a pas de ligne pour :new.num_op.. alors tu vas mettre NULL dans avoir_cpt.

    Je ferais plutôt comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    BEGIN
     SELECT  mtt_op   INTO v_mttop FROM operation P WHERE P.NUM_OP= :NEW.NUM_OP;
     IF :NEW.sens = 2 THEN v_mttop := - v_mttop; END IF;
    EXCEPTION WHEN NO_DATA_FOUND THEN .. -- a toi de voir ce qu'il faut faire
    END;
     
    IF :NEW.sens IN (1,2)
    THEN
     UPDATE COMPTE SET avoir_cpt = solde_cpt + v_mttop, solde_cpt = solde_cpt + v_mttop WHERE num_cpt = :NEW.num_cpt;
     IF SQL%ROWCOUNT = 0 THEN RAISE_APPLICATION_ERROR(-20001, 'numero de compte '|| :NEW.num_cpt ||' non valide'); END IF;
    END IF;

  11. #11
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Deux remarques:
    1. Gérer des cumuls dans les trigger c'est une mauvaise "bonne solution". Souvent ces cumuls deviens "déphasés" par rapport aux écritures détaillés (voir 2).
    2. Calculer des valeurs depuis une requête suivi d'une mise à jour d'une autre table en utilisant ces valeurs surtout pour gérer des cumuls n'est pas si anodine que cela semble et sans prendre beaucoup de soin ça risque de déphaser les cumuls de leurs valeurs réelles (voir 1).

Discussions similaires

  1. Réponses: 4
    Dernier message: 18/10/2004, 16h18
  2. Recuperer derniere valeur modifiée dans un trigger
    Par xabs dans le forum Développement
    Réponses: 2
    Dernier message: 06/08/2004, 16h22
  3. RAZ GENERATOR dans un trigger
    Par kase74 dans le forum SQL
    Réponses: 2
    Dernier message: 08/09/2003, 18h43
  4. select dans un trigger sous Postgresql
    Par kastor_grog dans le forum Requêtes
    Réponses: 1
    Dernier message: 03/09/2003, 17h00
  5. [PostgreSQL] Refus de STATEMENT dans un trigger
    Par alex2205 dans le forum Requêtes
    Réponses: 3
    Dernier message: 10/03/2003, 12h51

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