Partage
  • Partager sur Facebook
  • Partager sur Twitter

DELETE cascade

Sujet résolu
    5 juillet 2019 à 16:18:06

    Bonjours ,
    je suis sur les delete en castcade , je n'arrive pas a faire fonctionner le delete
    CREATE TABLE Utilisateur(
    	id INT (11) NOT NULL AUTO_INCREMENT,
    	`Name` VARCHAR(45) NULL DEFAULT NULL,
    	PRIMARY KEY (`ID`)
    )
    
    CREATE TABLE Groupe(
    	id INT (11) NOT NULL AUTO_INCREMENT,
    	`Name` VARCHAR(45) NULL DEFAULT NULL,
    	PRIMARY KEY (`ID`)
    )
    
    CREATE TABLE utilisateur_To_Groupe(
    id_Utilisateur INT (11) NOT NULL,
    id_Groupe INT (11) NOT NULL
    )
    
    INSERT INTO Utilisateur(Name) VALUES ('user1');
    INSERT INTO Utilisateur(Name) VALUES ('user2');
    
    INSERT INTO Groupe(Name) VALUES ('groupe1');
    
    INSERT INTO utilisateur_To_Groupe(id_Utilisateur,id_Groupe) VALUES (1,1);
    INSERT INTO utilisateur_To_Groupe(id_Utilisateur,id_Groupe) VALUES (2,1);
    le delete :
    DELETE 
    FROM Utilisateur
    WHERE Utilisateur.Name = 'user1'
    AND Utilisateur.Name = 'user2';
    avec le delete j'aimerai qu"il n'y a pas d'utilisateur n'y de groupe ,je ne c'est pas comment faire la FOREIGN KEY avec la cascade le problème c'est de bien supprimée le groupe si il n'y a plus Utilisateur rattacher .
    Merci d'avance pour votre aide .

    -
    Edité par di20 5 juillet 2019 à 16:18:42

    • Partager sur Facebook
    • Partager sur Twitter
      5 juillet 2019 à 17:26:35

      Bonjour,

      Dans cet exemple, tu as une relation n,n entre groupe et utilisateur : un utilisateur peut être dans n groupes, et un groupe peut contenir n utilisateurs.

      Le modèle est donc en trois tables, 2 tables d'entités (utilisateur et groupe) et une table de relation.

      Il est alors intéressant de créer des contraintes de clés étrangères dans la table de relation. Leur rôle sera d'assurer l'intégrité des données :

      • empêcher qu'il existe dans la table de relation une référence à un utilisateur inexistant
      • empêcher qu'il existe dans la table de relation une référence à un groupe inexistant

      Les options de contraintes permettant de conserver l'intégrité de la base vont être :

      • RESTRICT = Empêche de supprimer un groupe ou un utilisateur si il a une référence dans la table de relation
      • CASCADE = Lors de la suppression d'un groupe ou d'un utilisateur, supprime les enregistrements référencés dans la table de relation

      Il y a aussi deux options que je déconseille fortement :

      • SET NULL = Met à jour la table de relation avec NULL lorsque l'on supprime un utilisateur ou un groupe qui y est référencé. Cela entraîne la perte d'information ...
      • NO ACTION = ne fait rien, laisse une référence cassée dans la table de relation. Cela entraîne la perte d'intégrité.

      di20 a écrit:

      le problème c'est de bien supprimée le groupe si il n'y a plus Utilisateur rattacher

      Comme je viens de te le présenter, ce n'est pas le rôle de la contrainte de clé étrangère ...

      Si tu veux vraiment supprimer automatiquement un groupe qui n'a plus d'utilisateur, il faudra gérer cela avec un TRIGGER AFTER DELETE ON utilisateur_To_Groupe ...

      Mais je pense qu'il vaut mieux gérer cela manuellement et ponctuellement en listant les groupes sans utilisateur pour décider individuellement si il faut les supprimer ou non :

      SELECT G.*
      FROM
          groupe G
              LEFT JOIN utilisateur_To_Groupe UG
                  G.id = UG.id_Groupe
      WHERE UG.id_Groupe IS NULL
      • Partager sur Facebook
      • Partager sur Twitter
      Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
        6 juillet 2019 à 14:39:04

        Bonjour,

        Merci pour ton aide ,

        je suis tombé sur un 2eme problème qui y ressemble .

        CREATE TABLE `Utilisateur` (
        	`Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        	`Name` VARCHAR(20) NOT NULL,
        	`Password` CHAR(40) NOT NULL,
        	PRIMARY KEY (`Id`),
        	UNIQUE INDEX `Utilisateur_name_unique` (`Name`)
        )
        ENGINE=InnoDB;
        
        CREATE TABLE `AddressIP` (
        	`Id_utilisateur` INT(10) UNSIGNED NOT NULL,
        	`id_addressV4` INT(10) UNSIGNED NULL DEFAULT NULL,
        	`id_addressV6` INT(10) UNSIGNED NULL DEFAULT NULL,
        	`Date` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        	UNIQUE INDEX `AdressIp_Unique` (`Id_utilisateur`, `id_addressV4`, `id_addressV6`, `Date`),
        	INDEX `FK_AdressIp_IdAdress_To_AdressIpV4_id` (`id_addressV4`),
        	INDEX `FK_AdressIp_IdAdress_To_AdressIpV6_id` (`id_addressV6`),
        	CONSTRAINT `FK_AdressIp_IdAdress_To_AdressIpV4_id` FOREIGN KEY (`id_addressV4`) REFERENCES `AddressIPV4` (`Id`) ON DELETE CASCADE,
        	CONSTRAINT `FK_AdressIp_IdAdress_To_AdressIpV6_id` FOREIGN KEY (`id_addressV6`) REFERENCES `AddressIPV6` (`Id`) ON DELETE CASCADE,
        	CONSTRAINT `FK_AdressIp_IdUtilisateur_To_Utilisateur_id` FOREIGN KEY (`Id_utilisateur`) REFERENCES `Utilisateur` (`Id`) ON DELETE CASCADE
        )
        ENGINE=InnoDB;
        
        CREATE TABLE `AddressIPV4` (
        	`Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        	`A` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
        	`B` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
        	`C` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
        	`D` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
        	PRIMARY KEY (`Id`),
        	UNIQUE INDEX `AddressIpV4_Unique` (`A`, `B`, `C`, `D`)
        )
        ENGINE=InnoDB;
        
        CREATE TABLE `AddressIPV6` (
        	`Id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        	`A` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`B` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`C` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`D` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`E` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`F` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`G` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	`H` SMALLINT(5) UNSIGNED NULL DEFAULT NULL,
        	PRIMARY KEY (`Id`),
        	UNIQUE INDEX `AddressIpV6_Unique` (`A`, `B`, `C`, `D`, `E`, `F`, `G`, `H`)
        )
        ENGINE=InnoDB;

        comme le problème d'avant j'aimerai supprimée l'ip dans un supprime l'utilisateur .

        je ne voir pas comment faire ?

        merci d'avance pour ton aide .

        EDIT :
        le problème vient peut etre de la conception de la base de donnée .
        j'aimerai aussi optimiser la base de donnée . 

        j'ai test avec des Trigger sur "AddressIP" mais impossible de le faire fonctionner je suis sur mysql (linux)

        exemple de test simple :

        CREATE TRIGGER `D_Remove_AddressIp2` BEFORE DELETE ON `Utilisateur` FOR EACH ROW BEGIN
        
        	INSERT INTO Utilisateur (Utilisateur.Name , Utilisateur.Password) VALUES (OLD.Name,'DELETE');
        	
        END;

        et l'erreur :

        /* Erreur SQL (1064) : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3 */




         

        -
        Edité par di20 6 juillet 2019 à 14:48:29

        • Partager sur Facebook
        • Partager sur Twitter
          7 juillet 2019 à 14:36:50

          Bonjour,

          Pour optimiser ta partie de base concernant les IP, je commencerai par ne pas considérer chaque octet de l'adresse IP comme une colonne, à moins que tu n'en aies expressément besoin. Une adresse IP peut être considérée, en première approximation, comme "atomique" qui ne nécessite pas d'être divisée.

          Du coup, je mettrai l'IP comme un simple champ de type varchar, que tu peux discriminer par la longueur du varchar (pour IPv4 et IPv6). Tu peux aussi créer des DOMAINES pour chaque IP, c'est à dire un type personnalisé dont le contenu est conditionné par des règles obligatoires (format de l'adresse, longueur de l'adresse, valeurs limites, etc.). Cette pratique permet de s'assurer que le champ considéré contient bien une valeur de type IP valide (et pas n'importe quel texte).

          Concernant la structure de tes tables, soit tu restes avec tes 2 tables contenant tes 2 types d'adresses (avec les optimisations ci-dessus), soit tu considères que l'adresse IP est une table "générique" TYPE_ADRESSE :

          • UTLISATEUR (id_utilisateur [PK], etc.)
          • TYPE_ADRESSE (id_type_adresse [PK], type_adresse) où type_adresse = {IPv4|IPv6}
          • ADRESSE_IP (id_utilisateur, id_type_adresse, date, valeur_adresse), où ta clé primaire peut être composite [id_utilisateur, date, valeur] par exemple, en s'assurant qu'elle sera unique

          Un avantage que je vois à cette structure, c'est de faciliter les requêtes pour interroger les IP en fonction des dates, sans avoir à faire de jointure entre les 2 tables d'adresses IP.

          Ceci dit, les deux solutions se valent.

          K

          • Partager sur Facebook
          • Partager sur Twitter
            9 juillet 2019 à 11:44:13

            Pour les triggers, la logique est différente de ce à quoi tu penses. Va voir ce cours : https://openclassrooms.com/fr/courses/1959476-administrez-vos-bases-de-donnees-avec-mysql/1973090-triggers

            Pour supprimer la référence à une adresse IP quand l'utilisateur est supprimé, une clause ON DELETE CASCADE suffit sur la clé étrangère FK_AdressIp_IdUtilisateur_To_Utilisateur_id.
            Mais ça n'effacera pas les adresses de l'utilisateur dans AddressIPV4 et AddressIPV6. D'ailleurs il ne faut pas que ce soit le cas, parce qu'elles peuvent théoriquement servir à d'autres utilisateurs existants.

            -
            Edité par Zachee54 9 juillet 2019 à 11:44:50

            • Partager sur Facebook
            • Partager sur Twitter
              9 juillet 2019 à 14:26:41

              Zachee54 a écrit:

              ça n'effacera pas les adresses de l'utilisateur dans AddressIPV4 et AddressIPV6. D'ailleurs il ne faut pas que ce soit le cas, parce qu'elles peuvent théoriquement servir à d'autres utilisateurs existants.

              C'est ce que je voulais dire plus tôt :

              Benzouye a écrit:

              je pense qu'il vaut mieux gérer cela manuellement et ponctuellement en listant les groupes sans utilisateur pour décider individuellement si il faut les supprimer ou non

              Ce qui est transposable au cas des adresses IP ...

              • Partager sur Facebook
              • Partager sur Twitter
              Seul on va plus vite, ensemble on va plus loin ... A maîtriser : Conception BDD, MySQL, PHP/MySQL
                9 juillet 2019 à 20:48:35

                Bonjours ,

                merci pour votre aide , le problème est résolue j'ai m'y les adresse ip dans la même table .

                • Partager sur Facebook
                • Partager sur Twitter

                DELETE cascade

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown