2016-03-24 9 views
2

Ich habe ein Problem mit der Suche nach, wie die folgende Art der Assoziation zu erklären:Fremdschlüssel auf einem Teil des Verbund PK

sagen, dass ich eine Tabelle „Weekly“ als solche haben:

Weekly { 
Id : Int <= PK 

Week : Int 
Year : Int 
} 

und einem Tisch "Monthly":

Monthly{ 
Id : Int <= PK 

Month: Int 
Year : Int 
} 

ich habe auch eine "WeekMonth" Table:

Monthly{ 
Week : Int <= PK 
Month : Int <= PK 
Year : Int <= PK 
} 

Wie ihr wahrscheinlich erraten habt, möchte ich die Weekly mit WeekMonth und Monthly auch mit WeekMonth verknüpfen können.

Allerdings kann ich nicht säumen, um dies zu tun: ein Fremdschlüssel auf einem Teil des zusammengesetzten Primärschlüssels. Dennoch sind in meiner Tabelle WeekMonth sowohl das Jahr und die Woche als auch das Jahr und das Monat-Feld eindeutig, so dass es funktionieren kann.

Ich habe mehrere approch für dieses Problem versucht, aber als die kundenspezifische Zuordnung der Woche pro Monat ist ein Business-Bedarf, ich ein bisschen mit ihm steckte

+0

Angenommen, dies möglich war, überhaupt, würde es 4 oder 5 Datensätze in WeekMonth jeden Datensatz in Monat passend, so dass Sie würde den FK bitten, sich auf eine willkürliche PK zu beziehen. Wirklich brauchen Sie eine synthetische PK auf WeekMonth. –

+1

In der 'WeekMonth' Tabelle sind' Week' die Werte '1' bis' 4' oder '5' für jeden Monat oder sind die Wochen nummeriert' 1' bis '52' oder' 53' für das Jahr? Wie entspricht die Spalte "Woche" in der Tabelle "Wöchentlich" diesem? – MT0

+0

Während Sie in der Lage sein können, eine solche Beziehung in der Datenbank einzurichten, können Sie dies mit der aktuellen EF (6) nicht tun. Da EF in diesem Fall der Treiber ist, sollten Sie die Tags 'sql' und' oracle' aus der Frage entfernen. –

Antwort

2

in meinem WeekMonth Tisch, sowohl das Jahr und die Woche und das Jahr- und Monatsfeld sind offensichtlich einzigartig

Das ist nicht wahr. "Jahr und Woche" können einzigartig sein, aber es hängt davon ab, was "Woche" hier ist - wenn es die Woche innerhalb des Monats ist (d. H. 1-5), dann ist es nicht einzigartig. Wenn es die Woche innerhalb des Jahres (1-53) ist, dann ist es; aber Sie haben keinen eindeutigen oder primären Schlüssel für diese Kombination. Und "Jahr und Monat" ist nicht einzigartig, da Sie mehrere Einträge - entweder 4 oder 5 - für jede Kombination haben.

Wenn Sie einen zusammengesetzten primären (oder eindeutigen) Schlüssel haben, muss sich ein Fremdschlüssel auf alle Spalten in diesem PK beziehen - andernfalls wären sie nicht unbedingt eindeutig.

Ein natürlicher Schlüssel funktioniert nicht wirklich für Sie hier. Abgesehen davon, dass Sie die gewünschten Beziehungen nicht zulassen, duplizieren Sie Daten in den übergeordneten und untergeordneten Tabellen. Es wäre besser, einen synthetischen Schlüssel zu haben, z.B. Set aus einer Sequenz:

WeekMonth{ 
WeekMonth_Id : Int <= PK (synthetic, e.g. from sequence) 
Week   : Int <= } 
Month   : Int <= } UK 
Year   : Int <= } 
} 

Weekly { 
Weekly_Id  : Int <= PK 
WeekMonth_Id : Int <= FK to WeekMonth 
} 

Monthly{ 
Monthly_Id : Int <= PK 
WeekMonth_Id : Int <= FK to WeekMonth 
} 

Sie brauchen nicht das Jahr/Monat/Woche Werte in den untergeordneten Tabellen zu kopieren, wie Sie sie von der Mutter bekommen können. Und Sie sollten sie nicht duplizieren, da Sie nicht leicht garantieren können, dass die Übereinstimmung mit dem zugehörigen übergeordneten Datensatz sowie aus allgemeinen Normalisierungsgründen besteht.

Ich nehme an, Sie haben andere Daten in den wöchentlichen und monatlichen Tabellen, sonst wären sie ein bisschen sinnlos; Jede andere Tabelle, die einen FK zu einem solchen hat, könnte stattdessen einen FK zu WeekMonth verwenden.

Wenn Sie die einzelnen Jahres-/Monats-/Wochenwerte in den Kindtabellen duplizieren möchten, benötigen Sie zusätzlich zu Ihrem aktuellen PK separate eindeutige Schlüssel für diese Kombinationen. Sie würden also WeekMonth ändern, um einen eindeutigen Schlüssel für Jahr und Monat zu erhalten (was je nach "Woche" möglich ist) und einen anderen eindeutigen Schlüssel für Jahr und Monat - aber das ist keine einzigartige Kombination, die Sie nicht können Erstelle diesen Schlüssel.

2

Unter der Annahme, dass die WeekMonth Tabelle Week Werte 1 durch 53 für das Jahr hat dann:

CREATE TABLE WeekMonth(
    Week INT, 
    Month INT, 
    Year INT, 
    CONSTRAINT WeekMonth__W_M_Y__PK PRIMARY KEY (Week, Month, Year), 
    CONSTRAINT WeekMonth__W_Y__PK UNIQUE (Week, Year) 
); 

CREATE TABLE Monthly(
    ID INT PRIMARY KEY, 
    Month INT, 
    Year INT, 
    FirstWeek INT GENERATED ALWAYS 
    AS (TO_NUMBER(
      TO_CHAR(
      NEXT_DAY(
       TO_DATE(month||'-'||year, 'MM-YYYY') - 1, 
       'MONDAY' 
      ), 
      'WW' 
      ) 
     ) 
     ), 
    CONSTRAINT Monthly__M_Y__PK FOREIGN KEY (FirstWeek, Month, Year) 
    REFERENCES WeekMonth(Week, Month, Year) 
); 

CREATE TABLE Weekly(
    ID INT PRIMARY KEY, 
    Week INT, 
    Year INT, 
    CONSTRAINT Weekly__W_Y__PK FOREIGN KEY (Week, Year) 
    REFERENCES WeekMonth(Week, Year) 
); 
Verwandte Themen