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

MS SQL Server Discussion :

choix d'une clés primaire


Sujet :

MS SQL Server

  1. #1
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut choix d'une clés primaire
    Bonjour, j'ai un petit problème au niveau du choix de quelques clés primaire, nous somme distributeur d'une fiche x qui contient un numéro unique, nous vendons par unité de 500, cad a chaque fois q'un client demande une colis on lui livre 500 fiche de NumDebut à NumFin = NumDebut + 500, dans notre base on a des clients (qui sont connues a l'avance) avec un id + quelques autres infos et une table appelé livraison contenant le idCielnt(FK) et NumDebut et NumFin, mais je sais pas quelle est la vrai clé primaire, parce que un client peut avoir plusieurs livraison avec des numéro différent, si par exemple le client a une livraison dont le NumDebut = 147 et bien sur NumFin = 647, et je veux insérer un autre client avec NumDebut = 200 et NumFin = 700 ca doit pas passer parce que deja le 200 est est affecté au client 1 ?

  2. #2
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Commencez par écrire clairement votre enoncé, tel quel ça ne donne pas envie d'être lu

    Quelle est la structure actuelle de vos tables ?
    Pour quelle table cherchez-vous une clé primaire convenable ?
    Est-ce une nécessité métier que "d'allouer" 500 numéros de pièce consécutifs ?
    Si oui, vous devrez gérer la contrainte avec un trigger ou une contrainte CHECK faisant appel à une petite fonction

    Comme ça à chaud j'aurais mis :

    - Fiche : IDFiche <=> numéro unique de la fiche, autres infos
    - Pièce : IDPiece, Numero Piece (plage de 500), IDClient, IDLivraison
    - Client : IDClient, autres infos
    - Livraison : IDLivraison, autres infos

    @++

  3. #3
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    A chaud je mettrais la meme chose qu'elusket avec les mêmes remarques.

    La table livraison n'a pas besoin des informations concernant les fiches car celles-ci se trouvent deja dans la table Pièce.
    ++

  4. #4
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut
    Quelle est la structure actuelle de vos tables ?
    Ma base de donnée actuelle ne contient pas de Livraison, j'ai dejà la table Client donc je dois ajouter tout ce qui est livraison, c'est pour cette raison que j'ai ajouté une table livraison contenant idClient, DebutNumber, FinNumber, DateAttribution, et j'ai mis comme clé primaire DebutNumber, mais la j'ai pu detecter certains problemes par exemple je peux inserer dans ma table une livraison avec DebutNumber+ 2 par exemple, la chose qui n'est pas logique parce que la livraison de DebutNumber à FinNumber+500 est deja livré.

    Pour quelle table cherchez-vous une clé primaire convenable ?
    Pour la table Livraison
    Est-ce une nécessité métier que "d'allouer" 500 numéros de pièce consécutifs ?
    A chaque livraison, on livre par unité de 500 fiche, qui peut etre multiplié de 1 à 6 fois, mais dans ma base je persiste chaque unité de 500
    Si oui, vous devrez gérer la contrainte avec un trigger ou une contrainte CHECK faisant appel à une petite fonction
    J'ai pas bien saisi cette proposition ni la structuration de la base de donnée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Comme ça à chaud j'aurais mis :
     
    - Fiche : IDFiche <=> numéro unique de la fiche, autres infos
    - Pièce : IDPiece, Numero Piece (plage de 500), IDClient, IDLivraison
    - Client : IDClient, autres infos
    - Livraison : IDLivraison, autres infos
    Merci pour votre aide

  5. #5
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Effectivement, ce serait plus propre d'écrire :

    - Fiche : IDFiche (<=> numéro unique de la fiche), IDClient, IDLivraison, autres infos
    - Pièce : IDPiece, IDFiche, Numero Piece (plage de 500)
    - Client : IDClient, autres infos
    - Livraison : IDLivraison, autres infos

    Si j'ai compris, pour chaque fiche vous devez livrer un lot d'au minimum 500 pièces. Donc je vous ai proposé la table Piece, dans laquelle vous devrez créer 500 lignes par fiche.

    Autrement dit vous aurez :

    - un trigger qui, à l'insertion sur Fiche, crée 500 lignes dans la table Piece
    - une contrainte CHECK qui vérifie que le numéro de pièce est unique

    Toujours dans l'hypothèse de ce que je vous propose, vous aurez dans la table Fiche comme contraintes d'intégrité :

    - une clé étrangère référençant la colonne IDCLient de la table Client
    - une clé étrangère référençant la colonne IDLivraison de la table Livraison (je leur ai donné le même nom dans la table fiche)

    En espérant avoir été plus clair, surtout après auto-correction

    @++

  6. #6
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut
    Merci pour votre réponse, mais pour chaque livraison j'aurais 500fiche a livré, et non pas pour chaque fiche j'aurais 500pièce.

    En ce qui concerne
    une contrainte CHECK qui vérifie que le numéro de pièce est unique
    , cette contrainte sera crée au niveau Fiche ???

    Je suis pas trés convaincue par le fait d'ajouter une table et y inserer 500 ligne, la chose qui sera gourmende en mémoire, mais pourquoi ne pas faire une contrainte check directement et vérifier si le debutNumber existe entre debutNumber et EndNumber dans la table livraison ?

  7. #7
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    pour chaque livraison j'aurais 500fiche a livré
    Dans ce cas utilisez le trigger que je vous propose ici.

    cette contrainte sera crée au niveau Fiche ???
    Si votre numéro de fiche doit être unique, et ce quel que soit le client, oui.

    pourquoi ne pas faire une contrainte check directement et vérifier si le debutNumber existe entre debutNumber et EndNumber dans la table livraison ?
    Vous pouvez effectivement faire cela dans une fonction, et votre contrainte CHECK appellera cette fonction

    @++

  8. #8
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Vous pouvez effectivement faire cela dans une fonction, et votre contrainte CHECK appellera cette fonction
    , sur quel niveau je dois créer ma fonction et comment je vais l'appeler ?

  9. #9
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Un très bon exemple pour vous mettre sur la voie

    Une fonction, comme tout module SQL, se crée au niveau schéma

    @++

  10. #10
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut
    Bonjour, j'ai suivi l'exemple que vous m'avez donné, c'es interessant mais j'ai encore des problemes d'insertion, j'ai crée ma fonction qui teste sur l'intersection et l'inclusion des deux paramètres dd et df, et j'ai ajouté une contrainte a ma table, sauf que j'arrive pas a inserer au moins une ligne pour pouvoir testé la fiabilité de la fonction, il me dit que il y a un conflit avec la contrainte que je viens d'ajouté, sachant que la table est vide :

    Code : 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
    CREATE FUNCTION [dbo].[SelectLiasse](@DD int, @DF int)
    RETURNS BIT
    AS
    BEGIN
       DECLARE @B BIT;
       SET @B = 0;
    IF EXISTS(
    		 SELECT * 
    		 FROM   dbo.CVTLiasse 
    		 WHERE  (((@DD < EndNumber AND @DD > StartNumber) OR @DD = StartNumber OR @DD = EndNumber)
             OR ((@DF < EndNumber AND @DF > StartNumber) OR @DF = StartNumber OR @DF = EndNumber)
    		 OR (StartNumber < @DF OR StartNumber > @DD) 
    		 OR (EndNumber < @DF OR EndNumber > @DD)))
    SET @B = 1;
     
    RETURN @B;
    END

  11. #11
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 862
    Points : 53 013
    Points
    53 013
    Billets dans le blog
    6
    Par défaut
    Une contrainte CHECK ne peut appeler une fonction si cette fonction contient des appels à des tables.

    A +

  12. #12
    Membre habitué
    Inscrit en
    Août 2008
    Messages
    1 596
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 1 596
    Points : 175
    Points
    175
    Par défaut
    que dois je faire dans ce cas ? un trigger ? mais j'aurai toujours besoin d'appeler la table pour vérifier l'existence des données redondantes ?

  13. #13
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 862
    Points : 53 013
    Points
    53 013
    Billets dans le blog
    6
    Par défaut
    Le plus simple serait d'avoir une table paquet de fiche et une table fiche en relation 1:n avec n paramétré à 500.
    Bien entendu le paramètre 500 doit être stocké dans une table des paramètres, car il peut sans doute évoluer dans 6 mois, 1 an, 5 ans, 10 ans...

    Exemple :
    Code : 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
    CREATE TABLE T_PAQUET_PQT
    (PQT_ID        INT IDENTITY NOT NULL CONSTRAINT PK_PQT PRIMARY KEY,
     CLI_ID        INT NOT NULL          CONSTRAINT FK_PQT_CLI FOREIGN KEY 
                                         REFERENCES T_CLIENT_CLI (CLI_ID))
     
    CREATE TABLE T_FICHE_FCH
    (FCH_ID        INT IDENTITY NOT NULL CONSTRAINT PK_FCH PRIMARY KEY,
     PQT_ID        INT NOT NULL          CONSTRAINT FK_FCH_PQT FOREIGN KEY 
                                         REFERENCES T_PAQUET_PQT (PQT_ID))
     
    CREATE TABLE T_PARAMETRE_PRM
    (PRM_ID        INT IDENTITY NOT NULL CONSTRAINT PK_PRM PRIMARY KEY,                                     
     PRM_CODE      VARCHAR(64)  NOT NULL CONSTRAINT UK_PRM_COD UNIQUE,
     PRM_VALEUR    CHAR(32)     NOT NULL)
     
    INSERT INTO T_PARAMETRE_PRM 
    VALUES ('Cardinalité table T_FICHE_FCH', '500')
    Pour vérifier que la cardinalité soit toujours appliquées, il suffit d'insérer simultanément les 500 lignes et d'appliquer par déclencheur le code suivant :
    Code : 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
    CREATE TRIGGER E_FCH_IUD
    ON T_FICHE_FCH
    FOR INSERT, UPDATE, DELETE
    AS
     
    DECLARE @CARD_FICHE INT;
    SELECT @CARD_FICHE = CAST(PRM_VALEUR) 
    FROM   T_PARAMETRE_PRM
    WHERE  PRM_CODE = 'Cardinalité table T_FICHE_FCH';
     
    IF EXISTS(SELECT 0
              FROM   T_FICHE_FCH AS T1
                     INNER JOIN (SELECT *
                                 FROM   INSERTED
                                 UNION  DISTINCT
                                 SELECT *
                                 FROM   DELETED) AS T2
              GROUP  BY T1.PQT_ID
              HAVING COUNT(*) <> @CARD_FICHE)
    BEGIN
       ROLLBACK;
       RAISERROR('La cardinalité des fiches ne peut être différente de %d.', 16, 1, @CARD_FICHE);
    END
    A +

Discussions similaires

  1. Choix d'une clé primaire
    Par Pgs dans le forum Langage SQL
    Réponses: 2
    Dernier message: 22/07/2008, 18h44
  2. Réponses: 3
    Dernier message: 06/03/2007, 14h15
  3. choix des clés primaires
    Par dcollart dans le forum Décisions SGBD
    Réponses: 2
    Dernier message: 17/08/2005, 17h25
  4. Comment avoir 2 clés primaires dans une table
    Par Guigui_ dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 18/01/2005, 08h29
  5. [postgresql]creer une table avec plusieurs clés primaire??
    Par perlgirl dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/11/2004, 17h24

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