2017-05-22 2 views
0

Sagen wir, ich habe drei Tabellen. Ich werde diese Tabellen so einfach wie möglich machen, das Design Frage erläutern:Was ist die beste Vorgehensweise beim Entwerfen einer SQL-Tabelle, die sich auf Tabelle A, Tabelle B oder Tabelle A und B bezieht?

Benutzer:

CREATE TABLE users (user_id INT PRIMARY KEY); 

Networks:

CREATE TABLE networks (network_id INT PRIMARY KEY); 

Netzwerk-Benutzer:

CREATE TABLE network_users (
    network_id INT, 
    user_id INT, 
    PRIMARY KEY(network_id, user_id), 
    FOREIGN KEY(network_id) REFERENCES networks(network_id), 
    FOREIGN KEY(user_id) REFERENCES users(user_id) 
); 

Wie oben gezeigt, haben Benutzer eine Beziehung zwischen vielen und vielen Netzwerken, wie in der Tabelle Netzwerkbenutzer beschrieben. Das ist alles ziemlich konventionell.

Jetzt ist hier meine Frage:

Lassen Sie uns sagen, dass ich eine Nachrichten-Tabelle hinzufügen möchten, und ich möchte in der Lage sein, eine Nachricht zu speichern verschickt an:

  1. einen bestimmten Benutzer,
  2. eine spezifische Netzwerk,
  3. oder einen Benutzer in einem Netzwerk

Was ist der beste Design-Ansatz für den messag ist es Tisch?

Ich könnte eine Nachricht Tabelle wie folgt strukturiert:

CREATE TABLE messages (
    message_id INT PRIMARY KEY, 
    network_id INT, 
    user_id INT, 
    FOREIGN KEY(network_id) REFERENCES networks(network_id), 
    FOREIGN KEY(user_id) REFERENCES users(user_id) 
); 

wo:

  1. Nachrichten an einen bestimmten Benutzer das user_id Feldset und NULL für das network_id Feld
  2. Nachrichten gesendet haben gesendet In einem bestimmten Netzwerk ist das Feld network_id gesetzt und NULL für die Benutzer-ID
  3. Nachrichten, die an einen Benutzer innerhalb eines Netzwerks gesendet werden, haben sowohl die Netzwerk-ID als auch uns er_id Felder gesetzt

Aber ist das der beste Ansatz? Da die Felder network_id und user_id null sein können, muss ich einen separaten Primärschlüssel (message_id) erstellen, im Gegensatz zur Verwendung eines zusammengesetzten Primärschlüssels (von network_id und user_id), wie es sonst der Fall wäre.

+0

Wenn sich Benutzer A im Netzwerk N von Benutzer A im Netzwerk O (Senden einer Nachricht an einen bestimmten Benutzer in einem bestimmten Netzwerk) unterscheidet, befinden sich Benutzer und Netzwerke nicht in einer Viele-zu-Viele-Beziehung, sondern nur in einer Eins. zu viele. – Shadow

+0

Hm, kannst du das weiter erklären? Ein Benutzer kann sich in mehreren Netzwerken befinden und ein Netzwerk kann mehrere Benutzer enthalten. Ist das nicht eine viel zu viele Beziehung zwischen Netzwerken und Benutzern? Nachrichtenbeziehung Nr. 3 einer Nachricht an einen Benutzer innerhalb eines Netzwerks wäre eine Eins-zu-Viele-Beziehung, aber das ist eine Eins-zu-viele-Beziehung zwischen Nachrichten und Netzwerkbenutzern; Ich würde denken, dass die Beziehung messages-to-network_users die Beziehung zwischen Benutzern und Netzwerken nicht beeinflusst. – VKK

+0

Wenn sich derselbe Benutzer in mehreren Netzwerken befinden kann, ist es sinnlos, eine Nachricht an einen bestimmten Benutzer in einem bestimmten Netzwerk zu senden. Ich muss nur die Nachricht an den Benutzer senden. – Shadow

Antwort

1

Was Sie in Ihrer Frage beschreiben, ist als polymorphe Assoziation bekannt. Werfen Sie einen Blick auf this article, die einige Möglichkeiten beschreibt, diese zu modellieren.

Während der Artikel beschreibt, wie man eine polymorphe Assoziation so allgemein wie möglich modelliert, denke ich, dass Ihr Ansatz auch gut ist, weil höchstwahrscheinlich nicht mehr als 3 Nachrichtentypen (für einen Benutzer, ein Netzwerk und an einen Benutzer in einem Netzwerk)

+0

Dies ist der perfekte Artikel für meine Frage. Vielen Dank! – VKK

+0

Cool, ich bin froh, dass Sie es hilfreich fanden –

1

ein Ansatz, den ich gesehen habe, ist entity_id in messages zusammen mit entity_type zu haben, wo die Art, ob der Datensatz einem user oder einem network (oder eine andere Art später bezieht sich erzählt). This response hat einige interessante Beispiele für die Handhabung eines solchen Falles.

+0

In diesem Ansatz gibt es eine Möglichkeit, eine Fremdschlüsseleinschränkung zu definieren? – VKK

+0

Nicht mit MySQL, da die Fremdschlüsselreferenz zu starr ist, um mehr als eine Tabelle zu unterstützen. – Carl

0

Wenn Sie eine viele: viele Beziehung zwischen 3 Dinge (A, B, C):

CREATE TABLE ABC (
    a_id ..., 
    b_id ..., 
    c_id ..., 
    PRIMARY KEY(a_id, b_id, c_id), 
    INDEX(b_id, c_id, a_id), 
    INDEX(c_id, a_id, b_id) 
) ENGINE=InnoDB; 

Die Indizes können Sie von jedem Tisch zu den anderen Tischen zu bekommen.

Aber ... Lassen Sie uns einige Ihrer SELECTs bevor Sie sicher sein, dass dies das Beste ist.

+0

Korrigieren Sie mich, wenn ich falsch liege, aber müssen nicht alle Spalten eines Primärschlüssels nicht null sein? Wenn das der Fall ist, wie würde ich die Beziehungen # 1 und # 2 in meiner Frage behandeln? – VKK

+0

Hoppla. Plan A: Verwenden Sie einen bestimmten (nicht null) Wert anstelle von NULL. Plan B: Meine Antwort wird nicht funktionieren. –

Verwandte Themen