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

Requêtes MySQL Discussion :

Creation de table avec clef étrangère - doublon detecté


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut Creation de table avec clef étrangère - doublon detecté
    Bonsoir ,

    Pour faire simple , je dispose dans de 2 tables :

    Une table résiliation que je crée en étape 1 :

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE `dwh_type_resiliation` (
     `code_resiliation` tinyint(4) NOT NULL,
      `acronyme` varchar(5) NOT NULL,
      `libelle` varchar(80) NOT NULL,
      PRIMARY KEY (`code_resiliation`),
      UNIQUE KEY (`code_resiliation`),
      KEY (`code_resiliation`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

    En étape 2 je crée une table "abonnement". Un numéro d'abonnement peut être réinjecté dans la table à une date différente. La table est en mode "archive" . En somme la date max d'insertion/ de maj fait fois de dernière mise à jour. La clef primaire de la table est donc le couple numero abo + date max maj.

    Problème ma table détecte un doublon à la création. Cela vient du fait que je ne sais pas trop quoi mettre comme not null / default null / default 0 ...

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    CREATE TABLE `dwh_abonnement` (
    `numero_abonnement` INT(11) NOT NULL ,
    `produit` VARCHAR(16) ,
    `description` VARCHAR(80) ,
    `commentaire` VARCHAR(80) ,
    `periodicite` INT(11) ,
    `montant_pm` DOUBLE ,
    `tva` DOUBLE ,
    `date_effet` DATETIME ,
    `date_fin` DATETIME ,
    `dernier_mois_paye` DATETIME ,
    `debord_annee_suiv` TINYINT(3) ,
    `mes` DOUBLE ,
    `traite_crm` SMALLINT(6) ,
    `freq_facture` SMALLINT(6) ,
    `id_courrier` INT(11) ,
    `non_facturable` TINYINT(3) ,
    `infos_expert` VARCHAR(255) ,
    `fk_resiliation` TINYINT(4) ,
    `date_maj_ligne` DATETIME NOT NULL,
    PRIMARY KEY (`numero_abonnement`, `date_maj_ligne`,),
    UNIQUE key (`numero_abonnement`, `date_maj_ligne`),
    key (`numero_abonnement`, `date_maj_ligne`),
    CONSTRAINT `dwh_type_resiliation_fk` FOREIGN KEY (`fk_resiliation`) REFERENCES `dwh_type_resiliation` (`code_resiliation`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

    Vous pouvez m'aiguiller pour compléter ?

    Merci

  2. #2
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 222
    Points : 28 208
    Points
    28 208
    Par défaut
    Je ne connais pas les spécificités de MySql, mais déjà, par principe, une clé primaire ne peut pas être nulle. Et si c'est une clé composée, aucune de ses composantes ne doit (devrait?!) être nulle.

    Donc, ta colonne date_maj_ligne doit être, au minimum, avec la contrainte NOT NULL.

    Ensuite, il faut que tu mette dans cette colonne, ton "datetime" complet, c'est à dire, la date, mais aussi avec l'heure jusqu'à la milliseconde.
    Si tu ne mets que la date, comme valeur, depuis un code quelconque par exemple, tu ne pourras faire qu'une seule mise à jour par jour. Ca risque de coincer parfois.

    Perso, je vois 2 "bonnes" pratiques dans ton cas.
    1. Soit, avoir une colonne ID en clé primaire qui sert à rien, juste de clé primaire. Ensuite avoir une contrainte d'unicité sur tes 2 colonnes
    2. Soit, utiliser tes colonnes en clé primaire comme tu fais. En valeur par défaut, si MySQL le permet, tu remplis la colonne date avec la notion Current_Date, ou Now, je sais pas ce que c'est en MySQL. Ou sinon, alors tu passe par un déclencheur avant insertion, dans lequel tu vas forcer la valeur de la colonne à la valeur Current_Date (ou Now !)

  3. #3
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 337
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 337
    Points : 39 729
    Points
    39 729
    Billets dans le blog
    9
    Par défaut
    D'après le script communiqué, les deux colonnes de la PK sont bien "not null" comme il se doit

    Quelques remarques en marge du sujet :
    - colonnes "montant_pm" et "TVA" : il faut remplacer le type FLOAT par du DECIMAL, sinon vous aurez des valeurs décimales approximatives, ce qui est inacceptable en comptabilité !
    - colonne "MES" idem s'il s'agit d'un montant
    - colonne "dernier_mois_paye": à renommer "derniere_date_paiement" s'il s'agit d'une date ou à remplacer par du char(2) si c'est un mois seul, avec une contrainte check pour vérifier que la valeur est comprise entre "01" et "12"
    - colonne "acronyme" : du varchar(5) est contre-performant, à remplacer par du char(5)

  4. #4
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 950
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 950
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par tanaka59 Voir le message
    Problème ma table détecte un doublon à la création.
    Comment la création d'une table peut-elle générer une violation de clé primaire...
    Exécutez le code dans la console est copier coller ici le résultat avec message d'erreur.

    PS : A priori vos références UNIQUE KEY et KEY dans les créations de tables sont inutiles puisqu'ils sont identiques aux PRIMARY KEY QUI devraient être suffisantes.

  5. #5
    Inactif  

    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    3 064
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2011
    Messages : 3 064
    Points : 4 605
    Points
    4 605
    Par défaut
    Bonjour,

    Citation Envoyé par sevyc64 Voir le message
    Je ne connais pas les spécificités de MySql, mais déjà, par principe, une clé primaire ne peut pas être nulle. Et si c'est une clé composée, aucune de ses composantes ne doit (devrait?!) être nulle.
    Merci de la remarque , correction faite.

    Citation Envoyé par sevyc64 Voir le message
    Donc, ta colonne date_maj_ligne doit être, au minimum, avec la contrainte NOT NULL.
    Correction faite également

    Citation Envoyé par sevyc64 Voir le message
    Ensuite, il faut que tu mette dans cette colonne, ton "datetime" complet, c'est à dire, la date, mais aussi avec l'heure jusqu'à la milliseconde.
    Si tu ne mets que la date, comme valeur, depuis un code quelconque par exemple, tu ne pourras faire qu'une seule mise à jour par jour. Ca risque de coincer parfois.
    Le système / fichier / robot / personne devant alimenter le fichier on une spécificité je dirais même un convention . On travaille systématiquement au format YYYY-MM-DD HH:MM:SS . Donc pas de soucis pour éviter les doublons.

    Citation Envoyé par sevyc64 Voir le message
    Perso, je vois 2 "bonnes" pratiques dans ton cas.
    1. Soit, avoir une colonne ID en clé primaire qui sert à rien, juste de clé primaire. Ensuite avoir une contrainte d'unicité sur tes 2 colonnes
    2. Soit, utiliser tes colonnes en clé primaire comme tu fais. En valeur par défaut, si MySQL le permet, tu remplis la colonne date avec la notion Current_Date, ou Now, je sais pas ce que c'est en MySQL. Ou sinon, alors tu passe par un déclencheur avant insertion, dans lequel tu vas forcer la valeur de la colonne à la valeur Current_Date (ou Now !)
    Tout le problème de l'id est la. Mes données venant d'une autre base j'ai reçu pour consigne de ne pas utiliser d'id dans le nouveau système ... Question d'économie de champ. J'ai testé le fait d'en remettre un nouveau ... Bref avec MySQL c'est plus imbuvable qu'autre chose ! J'oublie l'id et je vais travailler avec des clefs composées ... pas le choix.

    Citation Envoyé par escartefigue Voir le message
    D'après le script communiqué, les deux colonnes de la PK sont bien "not null" comme il se doit
    J'ai bien tout rééplucher pour justement ne pas avoir de null intempestif.

    Citation Envoyé par escartefigue Voir le message
    Quelques remarques en marge du sujet :
    - colonnes "montant_pm" et "TVA" : il faut remplacer le type FLOAT par du DECIMAL, sinon vous aurez des valeurs décimales approximatives, ce qui est inacceptable en comptabilité !
    - colonne "MES" idem s'il s'agit d'un montant
    - colonne "dernier_mois_paye": à renommer "derniere_date_paiement" s'il s'agit d'une date ou à remplacer par du char(2) si c'est un mois seul, avec une contrainte check pour vérifier que la valeur est comprise entre "01" et "12"
    - colonne "acronyme" : du varchar(5) est contre-performant, à remplacer par du char(5)
    Merci de la remarque très juste , j'ai pas vu ces 3 coquilles ! Je corrige cela .

    Citation Envoyé par skuatamad Voir le message
    Comment la création d'une table peut-elle générer une violation de clé primaire...
    Exécutez le code dans la console est copier coller ici le résultat avec message d'erreur.

    PS : A priori vos références UNIQUE KEY et KEY dans les créations de tables sont inutiles puisqu'ils sont identiques aux PRIMARY KEY QUI devraient être suffisantes.
    Par sécurité , je note a chaque fois , primary + unique + key histoire de ne pas avoir de cas aberrant ...

    Voici ma nouvelle proposition et qui fonctionne (partiellement) , je n'ai pas mon pc pro sous la mains :

    Code mysql : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    CREATE TABLE `dwh_type_resiliation` (
      `code_resiliation` tinyint(4) NOT NULL,
      `abreviation` char(5) NOT NULL,
      `libelle` varchar(80) NOT NULL,
      PRIMARY KEY (`code_resiliation`),
      UNIQUE KEY (`code_resiliation`),
      KEY (`code_resiliation`)
    ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
     
    CREATE TABLE `dwh_abonnement` (
        `numero_abonnement` INT(11) NOT NULL,
    	`fk_produit` VARCHAR(16) NOT NULL  ,
    	`description` VARCHAR(80) DEFAULT NULL,
    	`commentaire` VARCHAR(80) DEFAULT NULL,
    	`periodicite` INT(11) DEFAULT '0',
    	`montant_pm` float DEFAULT '0',
    	`tva` DECIMAL DEFAULT '0',
    	`date_effet` DATETIME ,
    	`date_fin` DATETIME ,
    	`derniere_date_paiement` DATETIME ,
    	`debord_annee_suiv` TINYINT(3) DEFAULT '0',
    	`mes` DOUBLE DEFAULT '0',
    	`traite_crm` SMALLINT(6) DEFAULT '0',
    	`freq_facture` SMALLINT(6) DEFAULT '0',
    	`id_courrier` INT(11) DEFAULT '0',
    	`non_facturable` TINYINT(3) DEFAULT '0',
    	`infos_expert` VARCHAR(255) DEFAULT NULL,
    	`fk_resiliation` TINYINT(4) NOT NULL,
    	`date_maj_ligne` DATETIME NOT NULL,
    	PRIMARY KEY (`numero_abonnement`,`date_maj_ligne`,`fk_produit`,`fk_resiliation`),
    	UNIQUE key (`numero_abonnement`,`date_maj_ligne`,`fk_produit`,`fk_resiliation`),
    	key (`numero_abonnement`,`date_maj_ligne`,`fk_produit`,`fk_resiliation`),	
    	CONSTRAINT `dwh_type_resiliation_fk2` FOREIGN KEY (`fk_resiliation`) REFERENCES `dwh_type_resiliation` (`code_resiliation`) ,
    	CONSTRAINT `dwh_produit_fk2` FOREIGN KEY (`fk_produit`) REFERENCES `dwh_produit` (`code_produit`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

    * table sujette encore modification

    Merci a vous

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

Discussions similaires

  1. [Requête] creation de table avec un champ auto incrementé
    Par lucke_34 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 30/04/2020, 23h18
  2. creation de table avec contrainte
    Par jonathan1 dans le forum SQL
    Réponses: 4
    Dernier message: 29/08/2007, 15h28
  3. Creation de table avec un champ texte comme clé primaire
    Par Sytchev3 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 30/07/2007, 11h40
  4. [Hibernate]Table avec clé étrangère
    Par worldchampion57 dans le forum Hibernate
    Réponses: 6
    Dernier message: 02/06/2006, 11h50
  5. Newbie PgSQL->Probleme Creation de table avec FOREIGN KEY
    Par ralkif dans le forum PostgreSQL
    Réponses: 9
    Dernier message: 07/03/2006, 21h59

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