2009-07-27 15 views
21

Ich definiere eine Datenbank für ein Kunden-/Bestellsystem, wo es zwei sehr unterschiedliche Arten von Kunden gibt. Weil sie so unterschiedlich sind, wäre eine einzelne Kundentabelle sehr hässlich (sie wäre voller Nullspalten, da sie für einen Typ sinnlos sind).Mehrere Fremdschlüssel zu einer einzigen Spalte

Ihre Bestellungen sind jedoch im selben Format. Ist es möglich, eine CustomerId Spalte in meiner Bestellungstabelle zu haben, die einen Fremdschlüssel für beide Kundentypen hat? Ich habe es in SQL Server eingerichtet und es gibt mir keine Probleme erstellen die Beziehungen, aber ich bin noch zu versuchen, irgendwelche Daten einfügen.

Auch ich plane nHibernate als das ORM zu verwenden, könnte es irgendwelche Probleme geben, die eingeführt werden, indem man die Beziehungen so macht?

Antwort

19

Nein, Sie können kein einzelnes Feld als Fremdschlüssel für zwei verschiedene Tabellen verwenden. Wie würden Sie sagen, wo Sie nach dem Schlüssel suchen sollten?

Sie würden mindestens ein Feld benötigen, das angibt, um was für ein Benutzer es sich handelt, oder zwei separate Fremdschlüssel.

Sie können auch die für alle Benutzer gemeinsamen Informationen in einer Tabelle speichern und separate Tabellen für die spezifischen Informationen für die Benutzertypen verwenden, sodass Sie eine einzelne Tabelle mit Benutzer-ID als Primärschlüssel haben.

+1

Einverstanden. Normalisierung ist der Schlüssel hier. – jva

+1

@Guffa: -1 weil "Nein, Sie können nicht ein einzelnes Feld als Fremdschlüssel für zwei verschiedene Tabellen haben" - diese Aussage ist falsch (zumindest auf SQL Server 2005). Mach einen Wirbel. – Liao

+2

@Liao: Ich glaube nicht, dass Sie die Situation verstehen ... Wenn Sie zum Beispiel den Fremdschlüsselwert 42 haben, wie würden Sie wissen, ob es der Schlüssel in Tabelle A oder Tabelle B ist? – Guffa

3

Ein Fremdschlüssel kann nur einen einzelnen Primärschlüssel referenzieren, also keine. Sie können jedoch eine Brücke Tabelle verwenden:

CustomerA <---- CustomerA_Orders ----> Order 
CustomerB <---- CustomerB_Orders ----> Order 

So Bestellung nicht einmal hat einen Fremdschlüssel; ob das jedoch wünschenswert ist ...

1

Sie können einen Fremdschlüssel erstellen, der auf mehrere Tabellen verweist. Mit dieser Funktion können Sie Ihre Tabelle vertikal partitionieren und dennoch die referenzielle Integrität beibehalten. In Ihrem Fall ist dies jedoch nicht anwendbar.

Ihre beste Wette wäre, eine CustomerType-Tabelle mit möglichen Spalten zu haben - CustomerTypeID, CustomerID, wobei CustomerID die PK ist und dann Ihre OrderID-Tabelle an CustomerID verweist.

Raj

0

Zwei verschiedene Arten von Kunden ist ein klassischer Fall von Typen und Subtypen oder, wenn Sie es vorziehen, Klassen und Unterklassen. Here ist eine Antwort von einer anderen Frage.

Im Wesentlichen ist die Klassen-Tabellen-Vererbung Technik wie Arnands Antwort. Mit der Shared-Primary-Key-Technik können Sie Probleme umgehen, die durch zwei Arten von Fremdschlüsseln in einer Spalte entstehen. Der Fremdschlüssel ist eine Kunden-ID. Dadurch wird je nach Fall eine Zeile in der Kundentabelle und eine Zeile in der entsprechenden Kundentyptabelle identifiziert.

0

Wie gesagt, wenn der Schlüssel, sagen wir, 12345 ist, wie würden Sie wissen, in welcher Tabelle Sie nachschlagen? Sie könnten, denke ich, etwas tun, um sicherzustellen, dass sich die Schlüsselwerte für die beiden Tabellen nie überschneiden, aber das ist zu hässlich und schmerzhaft zu betrachten. Sie könnten ein zweites Feld haben, das sagt, welcher Kundentyp es ist. Aber wenn Sie zwei Felder haben wollen, warum haben Sie nicht ein Feld für Kundentyp 1 ID und ein anderes für Kundentyp 2 ID.

Ohne mehr über Ihre App zu wissen, ist mein erster Gedanke, dass Sie wirklich eine allgemeine Kundentabelle mit den beiden gemeinsamen Daten haben sollten und dann zwei zusätzliche Tabellen mit den spezifischen Daten für jeden Kundentyp haben.Ich würde denken, dass es eine Menge gemeinsamer Daten für die zwei geben muss - grundlegende Dinge wie Name und Adresse und zumindest die Kundennummer - und sich wiederholende Spalten über die Tabellen hinweg saugt viel Zeit. Die zusätzlichen Tabellen könnten dann auf die Basistabelle verweisen. Da es dann einen einzigen Schlüssel für die Basistabelle gibt, verdunstet das Problem, dass fremde Schlüssel wissen müssen, auf welche Tabelle Bezug genommen werden soll.

1

Ich geerbt eine SQL Server-Datenbank, wo dies getan wurde (eine einzelne Spalte in vier Fremdschlüssel Beziehungen mit vier unabhängigen Tabellen verwendet), also ja, es ist möglich. Mein Vorgänger ist weg, also kann ich nicht fragen, warum er das für eine gute Idee hielt.

Er verwendete eine GUID-Spalte ("uniqueidentifier" -Typ), um das Mehrdeutigkeitsproblem zu vermeiden, und er schaltete die Einschränkungsprüfung für die Fremdschlüssel aus, da garantiert ist, dass nur einer übereinstimmt. Aber ich kann mir viele Gründe vorstellen, die Sie nicht tun sollten, und ich habe mir keine Gründe dafür gedacht.

Ihr Sound klingt wie das klassische "Spezialisierung" -Problem, typischerweise gelöst durch Erstellen einer Elterntabelle mit den gemeinsamen Kundendaten, dann zwei untergeordnete Tabellen, die die für jede Kundenklasse eindeutigen Daten enthalten. Ihr Fremdschlüssel würde dann gegen die Eltern-Kundentabelle sein, und Ihre Entscheidung, welcher Kundentyp auf welcher Kind-Tabelle basieren würde, hätte einen übereinstimmenden Eintrag.

0
  1. Erstellen Sie eine "Kunden" -Tabelle, die alle Spalten enthält, die für beide Kundentypen dieselben Daten enthalten.
  2. als create table "customer_a" und "customer_b"
  3. Use "customer_id" von "Verbraucher" Tabelle als Fremdschlüssel in "customer_a" und "customer_b"

       customer 
            | 
        --------------------------------- 
        |        | 
    cusomter_a      customer_b 
    
Verwandte Themen