Supprimer un devis en totalité ou simplement une ligne
Bonjour,
J'ai quelques soucis pour traiter certaines opérations du MPD ci-dessous. Je travaille avec Firebird et Delphi 7 sous Windows
http://www.imageshotel.org/thumbs/seabsb/mpd4.jpg
Lorsque je veux supprimer une ligne du devis, il me faut d'abord supprimer la ligne présente dans la table de jointure "Lig_devis" puis dans la table "LIGNE", sauf si je mets mes clés étrangères de "Lig_devis" en cascade. Je gère cela correctement avec une procédure stockée ou pas.
Par contre, les choses se compliquent dès que je veux supprimer le devis en totalité, car il faut supprimer les lignes présentes dans "Lig_devis", puis dans "LIGNE" et enfin la ligne du devis dans "DEVIS".
Pour parvenir au résultat, si les clés étrangères de "Lig_devis" sont positionnées "NO ACTION", je dois créer une table temporaire, transférer les lignes de "Lig_devis" concernées, puis supprimer les éléments des tables "LIGNE" et "DEVIS". Ensuite, supprimer la table temporaire.
Bonjour la manœuvre
Je voudrais savoir s'il n'existe pas une méthode plus simple à l'aide d'un trigger ou d'une procédure stockée. Merci, de me donner votre avis.
Le positionnement des clés étrangères dans "Lig_devis" en cascade ne supprime pas ma difficulté car les lignes de la table "LIGNE" ne sont supprimées. La table "Lig_devis" est l'enfant de "DEVIS" et "LIGNE" d'où impossibilité en supprimant la ligne dans "Lig_devis" d'enlever la ligne liée dans "LIGNE". Si trigger avant Delete dans "Lig_devis", je me heurte à la récursivité.
Je tourne en rond et fais bouillir les quelques neurones qui me restent.
Je ne suis peut être pas très explicite, ceci explique peut-être cela, mais vous pouvez me demander des renseignements complémentaires si nécessaire
D'avance merci
Delete : trigger + variable de type Table
Bonsoir seabs,
Je ne connais ni Firebird ni Delphi 7, aussi je vous indique une solution avec SQL Server, en espérant qu’elle soit adaptable.
Avec SQL Server donc, on peut utiliser un trigger dans lequel on déclare une variable de type table, qui servira à mémoriser les valeurs des clés des lignes à supprimer dans la table LIGNE.
Pour me simplifier la vie à l’occasion des tests de ce trigger, j’ai remplacé systématiquement le type INT par le type CHAR(5).
Supposons que l’on soumette l’instruction suivante, pour supprimer le devis dev02 du client cli01 :
Code:
1 2 3 4
| DELETE FROM DEVIS
WHERE ClientId = 'cli01'
AND DevisId = 'dev02'
; |
Grâce au trigger, on intercepte les opérations de DELETE portant sur la table DEVIS. Avec l’option INSTEAD OF, on prend le contrôle avant que les suppressions ne soient effectuées.
Description du trigger :
Lignes 02 à 05 : déclaration de la variable @Temp, dont le contenu ne persistera que le temps de l’opération de Delete.
Lignes 07 à 15 : on mémorise dans @Temp les valeurs des clés des lignes à supprimer dans la table LIGNE. A noter que le SGBD fournit dans une table particulière (qu’il nomme Deleted) les lignes à supprimer dans la table DEVIS.
Lignes 17 à 23 : on supprime de qui doit l’être dans la table Lig_Devis.
Lignes 25 à 31 : on supprime ce qui doit l’être dans la table LIGNE.
Lignes 33 à 39 : on supprime ce qui doit l’être dans la table DEVIS.
Code:
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
| 01 CREATE TRIGGER DEVIS_DELETE ON DEVIS INSTEAD OF DELETE AS
02 DECLARE @Temp TABLE (
03 ClientId CHAR(5) NOT NULL,
04 LigneId CHAR(5) NOT NULL,
05 DevisId CHAR(5) NOT NULL)
06 ;
07 INSERT INTO @Temp
08 SELECT x.ClientId, z.LigneId, x.DevisId
09 FROM Deleted AS x
10 JOIN Lig_Devis AS y
11 ON x.ClientId = y.CLientId
12 AND x.DevisId = y.DevisId
13 JOIN LIGNE AS z
14 ON y.ClientId = z.CLientId
15 AND y.LigneId = z.LigneId
16 ;
17 DELETE FROM Lig_Devis
18 WHERE EXISTS
19 (SELECT ''
20 FROM @Temp AS y
21 WHERE Lig_Devis.ClientId = y.ClientId
22 AND Lig_Devis.DevisId = y.DevisId
23 )
24 ;
25 DELETE FROM LIGNE
26 WHERE EXISTS
27 (SELECT ''
28 FROM @Temp AS y
29 WHERE LIGNE.ClientId = y.ClientId
30 AND LIGNE.LigneId = y.LigneId
31 )
32 ;
33 DELETE FROM DEVIS
34 WHERE EXISTS
35 (SELECT ''
36 FROM DELETED AS y
37 WHERE DEVIS.clientid = y.clientid
38 AND DEVIS.devisId = y.devisId
39 )
40 ;
41 GO |
Maintenant, l’opération de suppression portant sur la table DEVIS réussira ou non selon le contenu de la table Commander et dépendra du choix NO ACTION ou CASCADE quant à contrainte référentielle liant ces deux tables.