Bonsoir almoha,
J’ai oublié de traiter de la réinitialisation...Envoyé par almoha
Si un utilisateur ne peut réinitialiser qu'une règle ayant le statut acquis, à charge de l’application de faire ce que doit :
Si MySQL était au niveau des autres SGBD, on aurait pu sous-traiter à un trigger la remise à 0 de Compteur et la suppression des lignes dans la table REPONDRE. Hélas, la modification de l’attribut Compteur est refusée quand on essaie de créer le trigger suivant (activé quand on modifie le statut ou autre donnée de la table CHOISIR) :UPDATE CHOISIR SET Statut = 'à acquérir' , Compteur = 0 WHERE UtilisateurId = identifiant de l’utilisateur AND RegleId = identifiant de la règle ; DELETE FROM REPONDRE WHERE UtilisateurId = identifiant de l’utilisateur AND RegleId = identifiant de la règle ;
CREATE TRIGGER CHOISIR_UPDATE_AFTER AFTER UPDATE ON CHOISIR FOR EACH ROW BEGIN SET @StatutAcquerir = 'à acquérir' ; SET @StatutAcquis = 'acquis' ; -- Au cas où Raoul demande la réinitilisation de son statut : IF old.Statut = @StatutAcquis AND new.Statut = @StatutAcquerir THEN DELETE FROM REPONDRE WHERE UtilisateurId = new.UtilisateurId AND RegleId = new.RegleId ; UPDATE CHOISIR SET Compteur = 0 -- Rejeté par MySQL... WHERE UtilisateurId = new.UtilisateurId AND RegleId = new.RegleId ; END IF ; END GO
A titre de curiosité, l’équivalent avec SQL Server (qui accepte la modification) :
Bon, tant pis, on se passera du trigger...CREATE TRIGGER CHOSIR_UPDATE_AFTER ON CHOISIR AFTER UPDATE AS DECLARE @StatutAcquerir AS VARCHAR(24) ; DECLARE @StatutAcquis AS VARCHAR(24) ; SET @StatutAcquerir = 'à acquérir' ; SET @StatutAcquis = 'acquis' ; -- Au cas où Raoul demande la réinitilisation de son statut : DELETE FROM REPONDRE WHERE EXISTS (SELECT '' FROM DELETED AS x, INSERTED AS y WHERE REPONDRE.UtilisateurId = x.UtilisateurId AND REPONDRE.RegleId = x.RegleId AND x.UtilisateurId = y.UtilisateurId AND x.RegleId = y.RegleId AND x.Statut = @StatutAcquis AND y.Statut = @StatutAcquerir) UPDATE CHOISIR SET Compteur = 0 WHERE EXISTS (SELECT '' FROM DELETED AS x, INSERTED AS y WHERE REPONDRE.UtilisateurId = x.UtilisateurId AND REPONDRE.RegleId = x.RegleId AND x.UtilisateurId = y.UtilisateurId AND x.RegleId = y.RegleId AND x.Statut = @StatutAcquis AND y.Statut = @StatutAcquerir) GO
Une remarque concernant la validité de l’attribut Statut : il est préférable de ne pas se tromper dans l’application, en écrivant par exemple « aquis » au lieu de « acquis », ça pourrait causer des dégâts...
1) Soit vous définissez une table STATUT à laquelle fait référence la table CHOISIR :
CREATE TABLE STATUT ( StatutId INT NOT NULL , StatutLibelle VARCHAR(24) NOT NULL , CONSTRAINT STATUT_PK (StatutId) ) ; CREATE TABLE CHOISIR ( UtilisateurId INT NOT NULL , RegleId INT NOT NULL , StatutId INT NOT NULL , Compteur INT NOT NULL DEFAULT 0 , CONSTRAINT CHOISIR_PK PRIMARY KEY (UtilisateurId, RegleId) , CONSTRAINT CHOISIR_UTILISATEUR_FK FOREIGN KEY (UtilisateurId) REFERENCES UTILISATEUR (UtilisateurId) ON DELETE CASCADE , CONSTRAINT CHOISIR_REGLE_FK FOREIGN KEY (RegleId) REFERENCES REGLE (RegleId) , CONSTRAINT CHOISIR_STATUT_FK FOREIGN KEY (StatutId) REFERENCES STATUT(StatutId) ) ;
2) Soit vous définissez un trigger « BEFORE INSERT » et un trigger « BEFORE UPDATE » pour la table CHOISIR afin de contrôler les valeurs prises par l'attribut Statut (avec les autres SGBD, on peut fusionner les deux triggers, mais pas avec MySQL...) :
CREATE TRIGGER CHOISIR_INSERT_BEFORE BEFORE INSERT ON CHOISIR FOR EACH ROW BEGIN SET @Table = 'CHOISIR' ; SET @StatutAcquerir = 'à acquérir' ; SET @StatutEnCours = 'acquisition en cours' ; SET @StatutAcquis = 'acquis' ; IF new.Statut NOT IN (@StatutAcquerir, @StatutEnCours, @StatutAcquis) THEN SET @Erreur = CONCAT('Table ', @Table, ', attribut Statut : la valeur "', new.Statut, '" est erronée.') ; SIGNAL SQLSTATE '45001' SET MESSAGE_TEXT = @Erreur ; END IF ; END GO CREATE TRIGGER CHOISIR_UPDATE_BEFORE BEFORE UPDATE ON CHOISIR FOR EACH ROW BEGIN SET @Table = 'CHOISIR' ; SET @StatutAcquerir = 'à acquérir' ; SET @StatutEnCours = 'acquisition en cours' ; SET @StatutAcquis = 'acquis' ; IF new.Statut NOT IN (@StatutAcquerir, @StatutEnCours, @StatutAcquis) THEN SET @Erreur = CONCAT('Table ', @Table, ', attribut Statut : la valeur "', new.Statut, '" est erronée.') ; SIGNAL SQLSTATE '45001' SET MESSAGE_TEXT = @Erreur ; END IF ; END GO
La jointure est possible, mais comme dans le cas général des nomenclatures elle doit être récursive... Les principaux SGBD proposent ce type de jointure, mais pas MySQL (décidément...)Envoyé par almoha
Ça n’est pas bien grave, on passera par une procédure récursive, et je suis en train d’en mettre une au point. Ça n’est pas très compliqué à faire, mais quand même, cela nécessite un peu d’huile de coude...
Je vous transmettrai cette procédure dès que.
Partager