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

Schéma Discussion :

Clé étrangère et double contrainte


Sujet :

Schéma

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 28
    Points : 21
    Points
    21
    Par défaut Clé étrangère et double contrainte
    Bonjour,

    Je souhaiterais avoir une clé étrangère dans une table X qui dépendent d'un champ d'un table Y OU Z


    Voilà le code que j'ai utilisé qui impose que la clé étrangère appartienne aux DEUX tables. Or, je voudrais qu'elle puisse appartenir à l'une OU à l'autre. Est-ce possible et avez-vous une solution?

    Merci de vos réponses par avance...
    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 Y(
       ChampY INTEGER,
    );
    
    
    CREATE TABLE Z(
       ChampZ INTEGER
    );
    
    
    CREATE TABLE X(
       ChampX INTEGER,
    
       CONSTRAINT fk_essai1 FOREIGN KEY (ChampX) REFERENCES Y(ChampY),
       CONSTRAINT fk_essai2 FOREIGN KEY (ChampX) REFERENCES Z(ChampZ),
    );

  2. #2
    Expert éminent sénior
    Avatar de fsmrel
    Homme Profil pro
    Spécialiste en bases de données
    Inscrit en
    Septembre 2006
    Messages
    8 112
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Spécialiste en bases de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2006
    Messages : 8 112
    Points : 31 586
    Points
    31 586
    Billets dans le blog
    16
    Par défaut
    Bonjour dev-linus,


    Il faudra assurer l’intégrité à coups de triggers :

    Un trigger pour s’assurer que lors d’un INSERT dans la table X, chaque ligne insérée a bien une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table X, chaque ligne modifiée conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un DELETE de la table Y, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un DELETE de la table Z, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table Y, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table Z, chaque ligne de la table X conserve toujours une référence à Y ou Z.

    Exemple avec MS SQL Server.

    Création des tables :
    Code SQL : 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
     
    CREATE TABLE X
    (
            KX               CHAR(04)      NOT NULL
          , Q                CHAR(04)      NOT NULL
          , FKX              CHAR(04)      NOT NULL
        , CONSTRAINT X_PK PRIMARY KEY (KX)
    ) ;
     
    CREATE TABLE Y
    (
            KY               CHAR(04)      NOT NULL
          , B                CHAR(04)      NOT NULL
          , C                CHAR(04)      NOT NULL
        , CONSTRAINT Y_PK PRIMARY KEY (KY)
    ) ;
     
    CREATE TABLE Z
    (
            KZ               CHAR(04)      NOT NULL
          , H                CHAR(04)      NOT NULL
          , J                CHAR(04)      NOT NULL
        , CONSTRAINT Z_PK PRIMARY KEY (KZ)
    ) ;

    Un échantillon de triggers :

    INSERT dans la table X :

    Code SQL : 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
     
    CREATE TRIGGER X_insert_tr ON X INSTEAD OF INSERT AS
     
        DECLARE @Count AS INT, @Err AS VARCHAR(48)
     
        SET @Count = (SELECT COUNT(*) 
                         FROM   INSERTED
                         WHERE  FKX IN (SELECT KY
                                      FROM   Y
                                      UNION
                                      SELECT KZ
                                      FROM   Z)) ;
        IF @Count = 0 
            BEGIN
                SELECT 'Insert into table X : Erreur d’intégrité' AS X, * FROM INSERTED
                RAISERROR (@Err, 10, 1) 
                RETURN 
            END
        ELSE
            BEGIN
                INSERT INTO X (KX, Q, FKX)
                       SELECT  KX, Q, FKX
                       FROM    INSERTED 
            END

    DELETE dans la table Y :

    Code SQL : 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
     
    CREATE TRIGGER Y_delete_tr ON Y INSTEAD OF DELETE AS
     
        DECLARE @Count AS INT, @Err AS VARCHAR(48)
     
        SET @Count = (SELECT COUNT(*) 
                      FROM   X JOIN DELETED ON X.FKX = DELETED.KY) ;
     
        IF @Count > 0
            BEGIN
                SET @Count = (SELECT COUNT(*) 
                              FROM   DELETED JOIN Z ON DELETED.KY = Z.KZ) ;
     
                IF @Count = 0 
                    BEGIN
                        SET @Err = 'Delete from table Y => Viol d’intégrité'
                        SELECT @Err, * FROM DELETED
                        RAISERROR (@Err, 10, 1) 
                        RETURN		
                    END
            END 
        ELSE
            BEGIN
                DELETE FROM Y
                       WHERE KY IN (SELECT DISTINCT KY
                                    FROM   DELETED) 
            END

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2011
    Messages : 28
    Points : 21
    Points
    21
    Par défaut
    Citation Envoyé par fsmrel Voir le message
    Bonjour dev-linus,


    Il faudra assurer l’intégrité à coups de triggers :

    Un trigger pour s’assurer que lors d’un INSERT dans la table X, chaque ligne insérée a bien une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table X, chaque ligne modifiée conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un DELETE de la table Y, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un DELETE de la table Z, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table Y, chaque ligne de la table X conserve toujours une référence à Y ou Z ;

    Un trigger pour s’assurer que lors d’un UPDATE de la table Z, chaque ligne de la table X conserve toujours une référence à Y ou Z.

    Exemple avec MS SQL Server.

    Création des tables :
    Code SQL : 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
     
    CREATE TABLE X
    (
            KX               CHAR(04)      NOT NULL
          , Q                CHAR(04)      NOT NULL
          , FKX              CHAR(04)      NOT NULL
        , CONSTRAINT X_PK PRIMARY KEY (KX)
    ) ;
     
    CREATE TABLE Y
    (
            KY               CHAR(04)      NOT NULL
          , B                CHAR(04)      NOT NULL
          , C                CHAR(04)      NOT NULL
        , CONSTRAINT Y_PK PRIMARY KEY (KY)
    ) ;
     
    CREATE TABLE Z
    (
            KZ               CHAR(04)      NOT NULL
          , H                CHAR(04)      NOT NULL
          , J                CHAR(04)      NOT NULL
        , CONSTRAINT Z_PK PRIMARY KEY (KZ)
    ) ;

    Un échantillon de triggers :

    INSERT dans la table X :

    Code SQL : 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
     
    CREATE TRIGGER X_insert_tr ON X INSTEAD OF INSERT AS
     
        DECLARE @Count AS INT, @Err AS VARCHAR(48)
     
        SET @Count = (SELECT COUNT(*) 
                         FROM   INSERTED
                         WHERE  FKX IN (SELECT KY
                                      FROM   Y
                                      UNION
                                      SELECT KZ
                                      FROM   Z)) ;
        IF @Count = 0 
            BEGIN
                SELECT 'Insert into table X : Erreur d’intégrité' AS X, * FROM INSERTED
                RAISERROR (@Err, 10, 1) 
                RETURN 
            END
        ELSE
            BEGIN
                INSERT INTO X (KX, Q, FKX)
                       SELECT  KX, Q, FKX
                       FROM    INSERTED 
            END

    DELETE dans la table Y :

    Code SQL : 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
     
    CREATE TRIGGER Y_delete_tr ON Y INSTEAD OF DELETE AS
     
        DECLARE @Count AS INT, @Err AS VARCHAR(48)
     
        SET @Count = (SELECT COUNT(*) 
                      FROM   X JOIN DELETED ON X.FKX = DELETED.KY) ;
     
        IF @Count > 0
            BEGIN
                SET @Count = (SELECT COUNT(*) 
                              FROM   DELETED JOIN Z ON DELETED.KY = Z.KZ) ;
     
                IF @Count = 0 
                    BEGIN
                        SET @Err = 'Delete from table Y => Viol d’intégrité'
                        SELECT @Err, * FROM DELETED
                        RAISERROR (@Err, 10, 1) 
                        RETURN		
                    END
            END 
        ELSE
            BEGIN
                DELETE FROM Y
                       WHERE KY IN (SELECT DISTINCT KY
                                    FROM   DELETED) 
            END
    Merci pour votre réponse.
    je vais essayer de traduire ca en MySQL.

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Votre problème a peut-être pour source une mauvaise modélisation des données !

    Au lieu de X, Y, Z, pourriez-vous nous dire plus contrairement ce qui justifie cette situation étrange ?

Discussions similaires

  1. Double contrainte de clé étrangère
    Par eperdu dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 21/04/2010, 15h49
  2. Réponses: 2
    Dernier message: 08/06/2006, 17h42
  3. Réponses: 5
    Dernier message: 28/04/2006, 11h55
  4. Contraintes de clés étrangères non respectées
    Par parfait dans le forum Requêtes
    Réponses: 7
    Dernier message: 28/07/2004, 12h48
  5. Réponses: 2
    Dernier message: 30/06/2004, 13h22

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