2013-02-28 4 views
2

La base de données ressemble à ceci. Forme courte:Plusieurs clés étrangères à plusieurs tables

CREATE TABLE LANDSLIDE (
     LNUMBER SERIAL NOT NULL, 
     PRIMARY KEY (LNUMBER) 
     ... 

Il 4 Les tableaux similaires (parties d'un glissement de terrain)

CREATE TABLE SCARP (
     SCPNUM CHAR(7) NOT NULL, 
     LNUMBER SMALLINT NOT NULL, 
     FOREIGN KEY (LNUMBER) REFERENCES LANDSLIDE (LNUMBER) ON DELETE CASCADE, 
     ... 
        ); 

par exemple scpnum = scp0001

CREATE TABLE ACCUMULATION (
     ACCUNUM CHAR(8) NOT NULL, 
     LNUMBER SMALLINT NOT NULL, 
     FOREIGN KEY (LNUMBER) REFERENCES LANDSLIDE (LNUMBER) ON DELETE CASCADE, 
     ... 
         ); 

par exemple. accunum = accu0001

CREATE TABLE FRONT (
     FRNUM CHAR(6) NOT NULL, 
     LNUMBER SMALLINT NOT NULL, 
     FOREIGN KEY (LNUMBER) REFERENCES LANDSLIDE (LNUMBER) ON DELETE CASCADE, 
     ... 
        ); 

par ex. frnum = fr0001

CREATE TABLE OTHER (
     OTHERNUM CHAR(9) NOT NULL, 
     LNUMBER SMALLINT NOT NULL, 
     FOREIGN KEY (LNUMBER) REFERENCES LANDSLIDE (LNUMBER) ON DELETE CASCADE, 
     ... 
        ); 

par exemple. othernum = other0001

Il existe une autre table, appelée matériau (pierres différentes, sols sur les différentes parties).

CREATE TABLE MATERIAL (
    MATNUMBER VARCHAR(9) NOT NULL, 
    ROCK, 
    DISTRIBUTION, 
    ... 
    PRIMARY KEY(MATNUMBER,ROCK,DISTRIBUTION,...), 
    CONSTRAINT material_matnumber_scarp_fkey FOREIGN KEY 
    (MATNUMBER) REFERENCES SCARP (SCPNUM) ON DELETE CASCADE, 
    CONSTRAINT material_matnumber_accumulation_fkey FOREIGN KEY 
    (MATNUMBER) REFERENCES ACCUMULATION (ACCUNUM) ON DELETE CASCADE, 
    CONSTRAINT material_matnumber_front_fkey FOREIGN KEY 
    (MATNUMBER) REFERENCES FRONT (FRNUM) ON DELETE CASCADE, 
    CONSTRAINT material_matnumber_other_fkey FOREIGN KEY 
    (MATNUMBER) REFERENCES OTHER (OTHERNUM) ON DELETE CASCADE 
        ); 

Lorsque j'insère des données sur le matériau (après avoir fait des entrées aux autres tables), il renvoie une erreur. ERREUR: insérer ou mettre à jour le tableau "matériel" viole la contrainte de clé étrangère "material_matnumber_accumulation_fkey" DETAIL: Key (matnumber) = (scp0001) est pas présent dans le tableau "accumulation"

Le matériel de table devrait ressembler à ceci:

MATNUMBER | ROCK | DISTRIBUTION | ... 
----------+------+--------------+------ 
scp0001 | A | lateral | ... 
scp0001 | B | lateral | ... 
accu0001 | B | central | ... 
scp0002 | C | NULL  | 
accu0002 | A | lateral | 
fr0002 | A | NULL  | 
scp0003 | B | cantral | 
accu0003 | B | lateral | 
other0003 | C | NULL  | 

Chaque entrée est unique, en raison du numéro de matricule!

+1

Eh bien, est-il une ligne dans '' ACCUMULATION' où ACCUNUM = 'scp0001''? –

+1

Ce que vous essayez de faire ne fonctionne pas.Le numéro de matricule 'scp0001' devra exister aussi dans toutes les tables que les clés étrangères, pas seulement' SCRAP'. Vous devrez créer plusieurs colonnes, une pour chaque clé étrangère. Vous pouvez les regrouper tous dans une colonne en utilisant une vue ou quelque chose. – JodyT

+0

Je pense que vos clés étrangères sont à l'envers. –

Répondre

2

Si je comprends bien, cela est un problème commun qui peut être résolu avec le motif supertype/sous-type. Vous pouvez également avoir 4 nullables colonnes FK dans le tableau Material mais voici ma suggestion:

CREATE TABLE Landslide (     --- no change here 
     LNumber SERIAL NOT NULL, 
     PRIMARY KEY (LNumber) 
     ... 

Vous dites: « Il y a 4 tableaux comme (parties d'un glissement de terrain) »

Ainsi, nous créons une table LandslidePart supplémentaire (ce qui est notre table "supertype"):

CREATE TABLE LandslidePart (
     PartType CHAR(1) NOT NULL, 
     PartNumber INT NOT NULL, 
     LNumber SMALLINT NOT NULL, 
     PRIMARY KEY (PartType, PartNumber), 
     CHECK (PartType IN ('S', 'A', 'F', 'O')),  --- the 4 subtypes 
     FOREIGN KEY (LNumber) REFERENCES Landslide (LNumber) ON DELETE CASCADE, 
     ...            --- other columns that are 
                 --- common in all 4 tables 
        ); 

Ensuite, nous avons nos 4 ("sous-type") tables, légèrement modifié:

CREATE TABLE Scarp (
     PartType CHAR(1) NOT NULL, 
     PartNumber INT NOT NULL, 
     PRIMARY KEY (PartType, PartNumber), 
     CHECK (PartType = 'S'), 
     FOREIGN KEY (PartType, PartNumber) 
      REFERENCES LandslidePart (PartType, PartNumber) 
      ON DELETE CASCADE, 
     ...       --- columns that are related to Scarp 
        ); 

CREATE TABLE Accumulation (
     PartType CHAR(1) NOT NULL, 
     PartNumber INT NOT NULL, 
     PRIMARY KEY (PartType, PartNumber), 
     CHECK (PartType = 'A'), 
     FOREIGN KEY (PartType, PartNumber) 
      REFERENCES LandslidePart (PartType, PartNumber) 
      ON DELETE CASCADE, 
     ...       --- columns that are related to Accumulation 
        ); 

--- We define in a similar way the other 2 tables: "Front" and "Other" 

Maintenant, nous pouvons définir la table Material que fait référence à la "Supertype" (LandslidePart) table et aucun des quatre:

CREATE TABLE Material (
    PartType CHAR(1) NOT NULL, 
    MatNumber INT NOT NULL, 
    Rock, 
    Distribution, 
    ... 
    PRIMARY KEY(PartType, MatNumber, Rock, Distribution, ...), 
    CONSTRAINT material_matnumber_landslidepart_fkey 
    FOREIGN KEY (PartType, MatNumber) 
     REFERENCES LandslidePart (PartType, PartNumber) 
     ON DELETE CASCADE, 
        ); 
+0

Oh, merci. Cela me semble assez clair. Je vais essayer ça! Puis-je créer d'autres tableaux, comme du matériel ayant la même relation avec les pièces? Comme un autre appelé EAU, par exemple. – Stefan

+0

Oui, vous pourriez. –

+0

Cela fonctionne si parfait. Merci beaucoup! – Stefan

-1

Vérifiez la longueur de vos clés étrangères et les types de données.

Toute la référence suivante à MATNUMBER VARCHAR(9) NOT NULL, dans MATERIAL

SCPNUM CHAR(7) NOT NULL, *should be* SCPNUM VARCHAR(9) NOT NULL, 
ACCUNUM CHAR(8) NOT NULL *should be* ACCUNUM VARCHAR(9) NOT NULL 
FRNUM CHAR(6) NOT NULL, *should be* FRNUM VarCHAR(9) NOT NULL, 
+0

Votez en bas Je vous demande pardon comment vous cascadez lorsque la longueur de la clé ne correspond pas? scp0001 ne va pas être dans la table * FRONT * comme FRNUM il ne peut accueillir que scp000. –

+0

Bon à savoir pourquoi voter vers le bas va penser que c'est des raisins verts –

+0

Je n'ai pas downvoted mais pensez-vous vraiment que ces changements vont résoudre le problème? Avoir une colonne qui référence 4 tables séparées, avec des valeurs évidemment différentes est le problème ici (ou mieux, l'un des problèmes). Votre réponse aidera simplement l'OP à passer le problème 'CREATE TABLE'. Il ne sera pas en mesure d'insérer des lignes du tout cependant. –

Questions connexes