Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 14/11/2007, 10h45   #1
Invité de passage
 
Inscription : juin 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 17
Points : 3
Points : 3
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 :
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
RSI06 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 11h08   #2
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
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
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 11h36   #3
Nouveau Membre du Club
 
Inscription : août 2006
Messages : 63
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 63
Points : 39
Points : 39
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 :
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
olive-andre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 12h02   #4
Invité de passage
 
Inscription : juin 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 17
Points : 3
Points : 3
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
RSI06 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 12h25   #5
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 450
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 450
Points : 4 209
Points : 4 209
Il suffit de gérer tous les cas
Code :
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
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 12h28   #6
Nouveau Membre du Club
 
Inscription : août 2006
Messages : 63
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 63
Points : 39
Points : 39
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 :
UPDATE T_Fournisseur SET nb_facture = nCount WHERE id_fournisseur = :old.id_fournisseur;
penses aussi à soustraire les factures que tu détruits, etc....
olive-andre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 12h29   #7
Nouveau Membre du Club
 
Inscription : août 2006
Messages : 63
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 63
Points : 39
Points : 39

Désolé, MCM a tiré plus vite que moi ....
olive-andre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 12h46   #8
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 450
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 450
Points : 4 209
Points : 4 209
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 14h08   #9
Invité de passage
 
Inscription : juin 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 17
Points : 3
Points : 3
Citation:
Envoyé par McM Voir le message
Il suffit de gérer tous les cas
Code :
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
RSI06 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 17h23   #10
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 319
Points : 5 837
Points : 5 837
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
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 18h33   #11
Membre Expert
 
Avatar de Garuda
 
Homme Philippe CHIRCOP
Chef de projet
Inscription : juin 2007
Messages : 1 109
Détails du profil
Informations personnelles :
Nom : Homme Philippe CHIRCOP
Localisation : France

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

Informations forums :
Inscription : juin 2007
Messages : 1 109
Points : 1 559
Points : 1 559
Citation:
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 :
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 :
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 :
SELECT id_fournisseur,nom_fournisseur,nb_factures(cod_four) FROM t_fournisseur
__________________
Garuda गरूड
Brahmâ la Guerre et Vishnu la Paix

Oracle 10.2.0.4 - Forms6i patch 17 - Toad 11.1 - sharePoint 2010
Garuda est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 19h22   #12
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 450
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 450
Points : 4 209
Points : 4 209
Oui, mais bonjour le nb de lectures logiques dans certains cas.
__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 14/11/2007, 21h30   #13
Rédacteur/Modérateur
 
Avatar de orafrance
 
Inscription : janvier 2004
Messages : 15 861
Détails du profil
Informations personnelles :
Âge : 35

Informations forums :
Inscription : janvier 2004
Messages : 15 861
Points : 16 212
Points : 16 212
surtout une fonction dans une requête, c'est pas génial
orafrance est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/11/2007, 11h10   #14
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 319
Points : 5 837
Points : 5 837
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 :
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é.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/11/2007, 13h06   #15
Invité de passage
 
Inscription : juin 2007
Messages : 17
Détails du profil
Informations forums :
Inscription : juin 2007
Messages : 17
Points : 3
Points : 3
Par défaut finalisation

La solution de MCM fonctionne parfaitement
Merci à tous
RSI06 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/11/2007, 13h53   #16
McM
Expert Confirmé Sénior
 
Inscription : juillet 2003
Messages : 3 450
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 3 450
Points : 4 209
Points : 4 209
Yeeesss...

__________________
More Code : More Bugs. Less Code : Less Bugs
McM est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 15/11/2007, 14h39   #17
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
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 : 3 319
Points : 5 837
Points : 5 837
Sauf que j’arrive à obtenir ce message

Code :
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é

Citation:
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.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/11/2007, 17h24   #18
Nouveau Membre du Club
 
Inscription : août 2006
Messages : 63
Détails du profil
Informations forums :
Inscription : août 2006
Messages : 63
Points : 39
Points : 39
Citation:
Envoyé par McM Voir le message
Yeeesss...


--
je mets un -- car je n'ai pas été aussi précis que toi !
Oliv.
olive-andre est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h13.


 
 
 
 
Partenaires

Hébergement Web