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 :

Maj par trigger


Sujet :

PL/SQL Oracle

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 19
    Par défaut Maj par trigger
    Bonjour à tous et d'avance merci à eux qui pourront m'aider.
    Je vous explique mon problème :
    J'ai 2 tables :
    - 1 table T_Fournissseurs
    - 1 table T_Factures

    La table T_Fournisseurs a 1 colonne "nb_factures"

    Ma question est simple : comment puis-je compter le nombre total de facture pour un fournisseur donné au moment de la validation d'une nouvelle facture dans la table T_Facture ?

    J'a voulu faire un trigger AFTER sur la table T_Factures
    Extrait du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Select count(*) into nCount from T_Facture where id_fournisseur = :old.id_fournisseur;
    update T_Fournisseur set nb_facture = nCount where id_fournisseur = :old.id_fournisseur;
    Mais j'ai l'erreur oracle de la table en mutation car je veux lire la table T_Factures qui vient d'être mise à jour alors que mon trigger est de type AFTER.

    Je ne comprend pas.

    Connaissez-vous une meilleur solution ?

    Merci

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    une recherche sur le forum devrait t'apporter des éléments, un sujet a été l'objet d'un long débat pas plus tard que la semaine dernière

    PS : le code du trigger serait nettement plus intéressant avec les balises ad hoc

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 72
    Par défaut Ecrit une procédure
    Utilise une procédure ou une fonction (tu pourras utiliser cette derniere dans une requète) qui se chargera
    1) de l'insertion dans la table T_FACTURE
    2) de la mise à jour du compteur dans la table T_FOURNISSEUR.

    Sinon, tu peux aussi utiliser une vue sur la table T_FOURNISSEUR de ce type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    create or replace view V_FOURNISSEUR as 
    select 
        id_fournisseur as id_fournisseur,
        (select count(*) 
            from T_FACTURE FA 
            where FA.id_fournisseur = FO.id_fournisseur) as nb_facture
    from T_FOURNISSEUR FO ;
    Elle marche

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 19
    Par défaut
    Merci de ta réponse olive-andré mais l'insert se fait via le navigateur WEB.

    La vue ne m'apportera rien car la colonne nb_facture est sujet à des calculs à d'autres moments.

    Merci

    L'idée de la procédure est intéressante
    Je vais y travailler

  5. #5
    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
    Il suffit de gérer tous les cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    IF INSERTING
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) + 1 WHERE id_fournisseur = :NEW.id_fournisseur;
    ELSIF DELETING
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) - 1 WHERE id_fournisseur = :OLD.id_fournisseur;
    ELSIF UPDATING AND :OLD.id_fournisseur <> :NEW.id_fournisseur
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) - 1 WHERE id_fournisseur = :OLD.id_fournisseur;
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) + 1 WHERE id_fournisseur = :NEW.id_fournisseur;
    END IF;
    Edit c'est un trigger BEFORE INSERT OR UPDATE OR DELETE FOR EACH ROW

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 72
    Par défaut
    je ne sais pas ce que tu entends par
    Citation Envoyé par RSI06 Voir le message
    La vue ne m'apportera rien car la colonne nb_facture est sujet à des calculs à d'autres moments.
    mais, pourquoi dans le code de ton trigger tu ne calcules juste pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UPDATE T_Fournisseur SET nb_facture = nCount WHERE id_fournisseur = :old.id_fournisseur;
    penses aussi à soustraire les factures que tu détruits, etc....

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 72
    Par défaut

    Désolé, MCM a tiré plus vite que moi ....

  8. #8
    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

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 19
    Par défaut
    Citation Envoyé par McM Voir le message
    Il suffit de gérer tous les cas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    IF INSERTING
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) + 1 WHERE id_fournisseur = :NEW.id_fournisseur;
    ELSIF DELETING
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) - 1 WHERE id_fournisseur = :OLD.id_fournisseur;
    ELSIF UPDATING AND :OLD.id_fournisseur <> :NEW.id_fournisseur
    THEN
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) - 1 WHERE id_fournisseur = :OLD.id_fournisseur;
    	UPDATE T_Fournisseur SET nb_facture = NVL(nb_facture,0) + 1 WHERE id_fournisseur = :NEW.id_fournisseur;
    END IF;
    Edit c'est un trigger BEFORE INSERT OR UPDATE OR DELETE FOR EACH ROW
    Je vais tenter cette solution.
    Je vous tiens au courant

  10. #10
    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
    Je ne sais plus pourquoi mais il me semble qu’il faut ajouter aussi une contrainte sur la table facture. Mais j’ai du mal à me rappeler pourquoi

  11. #11
    Membre Expert Avatar de Garuda
    Homme Profil pro
    Chef de projet / Urbaniste SI
    Inscrit en
    Juin 2007
    Messages
    1 285
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Vaucluse (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Chef de projet / Urbaniste SI
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 285
    Par défaut
    Ma question est simple : comment puis-je compter le nombre total de facture pour un fournisseur donné au moment de la validation d'une nouvelle facture dans la table T_Facture ?
    Si je puis me permettre, revenons à l'essentiel : est-ce besoin de stocker ce nombre ?
    A voir pour les bidouilles à faire pour l'alimenter, on y fera Jamais confiance !!!
    Et bonjour la dénormalisation.

    Donc je rejoins olive_andre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Sinon, tu peux aussi utiliser une vue sur la table T_FOURNISSEUR de ce type
    Moi, dans ces cas la, je fais une fonction (relire les papiers de TOM KYTE et STEVE FEURSTEIN) !!!
    Si j'en ai besoin dans un select, pas de pb ! Et le compteur est toujours à jour !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    CREATE OR REPLACE FUNCTION nb_facture (p_four IN id_fournisseur%TYPE)
       RETURN NUMBER
    IS
       n   NUMBER;
    BEGIN
       SELECT COUNT (*)
         INTO n
         FROM t_facture
        WHERE id_fournisseur = p_four;
     
       RETURN NVL (n, 0);
    END nb_facture;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Select id_fournisseur,nom_fournisseur,nb_factures(cod_four) from t_fournisseur

  12. #12
    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
    Oui, mais bonjour le nb de lectures logiques dans certains cas.

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

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    surtout une fonction dans une requête, c'est pas génial

  14. #14
    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
    Citation Envoyé par Garuda Voir le message
    Si je puis me permettre, revenons à l'essentiel : est-ce besoin de stocker ce nombre ?
    A voir pour les bidouilles à faire pour l'alimenter, on y fera Jamais confiance !!!
    Et bonjour la dénormalisation.

    Donc je rejoins olive_andre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Sinon, tu peux aussi utiliser une vue sur la table T_FOURNISSEUR de ce type
    Moi, dans ces cas la, je fais une fonction (relire les papiers de TOM KYTE et STEVE FEURSTEIN) !!!
    ...
    Bonjour,

    Il est possible que l’application imposé le stockage du cumul. Moi je n’appel pas ça dénormalisation.
    En plus Tom Kyte ne dit ce que vous dite . Il recommande l’utilisation d’une vue matérialisée avec le paramètre QUERY_REWRITE, mise en place du CBO de telle façon que la requête qui calcul le cumul sur la table de base se exécute en fait sur la vue matérialisé.

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 19
    Par défaut finalisation
    La solution de MCM fonctionne parfaitement
    Merci à tous

  16. #16
    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
    Yeeesss...


  17. #17
    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
    Sauf que j’arrive à obtenir ce message

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SQL> update t_factures set id_fournisseur = 1 where id = 2;
    update t_factures set id_fournisseur = 1 where id = 2
           *
    ERREUR à la ligne 1 :
    ORA-00060: Détection d'interblocage pendant l'attente d'une ressource
    ORA-06512: à "MNI.BIUD", ligne 11
    ORA-04088: erreur lors d'exécution du déclencheur 'MNI.BIUD'
    et Oracle (Oracle 9i Database Concepts) dit que j’ai mal programmé

    Avoid Deadlocks
    Multitable deadlocks can usually be avoided if transactions accessing the same tables lock those tables in the same order, either through implicit or explicit locks. For example, all application developers might follow the rule that when both a master and detail table are updated, the master table is locked first and then the detail table. If such rules are properly designed and then followed in all applications, deadlocks are very unlikely to occur.
    When you know you will require a sequence of locks for one transaction, consider acquiring the most exclusive (least compatible) lock first.

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    72
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 72
    Par défaut
    Citation Envoyé par McM Voir le message
    Yeeesss...


    --
    je mets un -- car je n'ai pas été aussi précis que toi !
    Oliv.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. modification d'un champs par trigger
    Par witch dans le forum SQL Procédural
    Réponses: 17
    Dernier message: 06/10/2007, 19h50
  2. Clefs primaires assignées par trigger
    Par Costalfy dans le forum Hibernate
    Réponses: 8
    Dernier message: 10/08/2007, 11h59
  3. RAISE_APPLICATION_ERROR + INSERT déclenchés par trigger
    Par petit_crabe dans le forum PL/SQL
    Réponses: 2
    Dernier message: 26/06/2007, 15h11
  4. maj par innerHTML -> pas de back
    Par Bruno2000 dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 22/06/2006, 11h22
  5. id autoincrémenté par trigger
    Par dumser1 dans le forum Développement
    Réponses: 4
    Dernier message: 08/02/2006, 13h54

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