Wie implementiere ich beim Entwerfen von Tabellen Eins-zu-Eins-, Eins-zu-Viele- und Viele-zu-Viele-Beziehungen?

281

Kann jemand erklären, wie man Eins-zu-Eins-, Eins-zu-Viele- und Viele-zu-Viele-Beziehungen implementiert, während man Tabellen mit einigen Beispielen entwirft?

Arsenal
quelle
Die Implementierung variiert in der Regel je nach RDBMS-Ziel. Auf welchen Anbieter richten Sie sich?
Billinkc
1
Das ist keine Hausaufgabenfrage ... !! Ich bereite mich auf ein Interview vor. Also dachte ich, ich sollte hier fragen ... Ich habe versucht zu googeln, aber ich habe keinen guten Artikel gefunden, in dem ich all dies in einem erklärt bekomme ... !!
Arsenal
Ich ziele auf Orakel-Datenbank .. !!
Arsenal
Vielleicht möchten Sie auch diesen Beitrag lesen .... stevencalise.wordpress.com/2010/09/01/… Ich würde genau auf die Punkte 2 und 3
achten
3
@tsells Manchmal werden Ihnen Fragen gestellt, die nicht für die Inhalte Ihres Lebenslaufs oder direkt für die Jobanforderungen gelten. Ich erhielt eine Liste von Personen, die mich in einem Unternehmen interviewen würden, und einer war ein DB-Experte. Ich hatte kein SQL in meinem Lebenslauf, aber ich habe ein paar einfache SQL-Abfragen aufgefrischt. Es hat geholfen, und ich habe den Job bekommen. Ich habe später herausgefunden, dass der Personalchef besorgt war, wie die Kandidaten unter Druck reagieren. Geben sie ihre Grenzen zu oder täuschen sie sich durch? Wenn sie ihre Grenzen zugeben, versuchen sie es trotzdem oder geben sie zu früh auf?
Doug Cuthbertson

Antworten:

478

Eins-zu-eins: Verwenden Sie einen Fremdschlüssel für die referenzierte Tabelle:

student: student_id, first_name, last_name, address_id
address: address_id, address, city, zipcode, student_id # you can have a
                                                        # "link back" if you need

Sie müssen auch eine eindeutige Einschränkung für die Fremdschlüsselspalte ( addess.student_id) festlegen, um zu verhindern, dass sich mehrere Zeilen in der untergeordneten Tabelle ( address) auf dieselbe Zeile in der referenzierten Tabelle ( student) beziehen .

Eins-zu-viele : Verwenden Sie einen Fremdschlüssel auf der vielen Seite der Beziehung, die mit der "einen" Seite verknüpft ist:

teachers: teacher_id, first_name, last_name # the "one" side
classes:  class_id, class_name, teacher_id  # the "many" side

Viele-zu-Viele : Verwenden Sie eine Junction-Tabelle ( Beispiel ):

student: student_id, first_name, last_name
classes: class_id, name, teacher_id
student_classes: class_id, student_id     # the junction table

Beispielabfragen:

 -- Getting all students for a class:

    SELECT s.student_id, last_name
      FROM student_classes sc 
INNER JOIN students s ON s.student_id = sc.student_id
     WHERE sc.class_id = X

 -- Getting all classes for a student: 

    SELECT c.class_id, name
      FROM student_classes sc 
INNER JOIN classes c ON c.class_id = sc.class_id
     WHERE sc.student_id = Y

NullUserException
quelle
1
Was ist ein gutes Beispiel dafür, wann der "Link zurück" in der Eins-zu-Eins-Beziehung nützlich ist? Vielen Dank für die klare und prägnante Antwort.
dev_feed
1
@dev_feed In Bezug auf das Datenbankdesign sehe ich den Link zurück nicht als vorteilhaft an, aber wenn Sie das obige Beispiel verwenden, könnte der Link zurück das Auffinden eines studentbestimmten An vereinfachen address.
Kanten
@NullUserException Müssen wir 3 Tabellen für eine Viele-zu-Viele-Beziehung benötigen? Kann dies nicht durch zwei Tabellen, die Viele-zu-Viele-Beziehung, durchgeführt werden?
1
@Cody Jede student_classesZeile sollte nur eine Eins-zu-Eins-Beziehung haben. Wenn studentAin classAund ist classB, sollten zwei Zeilen vorhanden sein student_classes, eine für welche Beziehung.
NullUserException
11
In einer Eins-zu-Eins-Beziehung sollte das Verknüpfungsfeld in beiden Tabellen eindeutig sein. Es handelt sich wahrscheinlich um eine PK für eine Tabelle, die die Eindeutigkeit garantiert, für die andere Tabelle ist jedoch möglicherweise ein eindeutiger Index erforderlich.
HLGEM
70

Hier sind einige Beispiele aus der Praxis für die Arten von Beziehungen:

Eins zu eins (1: 1)

Eine Beziehung ist genau dann eins zu eins, wenn ein Datensatz aus Tabelle A mit maximal einem Datensatz in Tabelle B verknüpft ist.

Um eine Eins-zu-Eins-Beziehung herzustellen, muss der Primärschlüssel von Tabelle B (ohne verwaisten Datensatz) der Sekundärschlüssel von Tabelle A (mit verwaisten Datensätzen) sein.

Beispielsweise:

CREATE TABLE Gov(
    GID number(6) PRIMARY KEY, 
    Name varchar2(25), 
    Address varchar2(30), 
    TermBegin date,
    TermEnd date
); 

CREATE TABLE State(
    SID number(3) PRIMARY KEY,
    StateName varchar2(15),
    Population number(10),
    SGID Number(4) REFERENCES Gov(GID), 
    CONSTRAINT GOV_SDID UNIQUE (SGID)
);

INSERT INTO gov(GID, Name, Address, TermBegin) 
values(110, 'Bob', '123 Any St', '1-Jan-2009');

INSERT INTO STATE values(111, 'Virginia', 2000000, 110);

Eins zu viele (1: M)

Eine Beziehung ist genau dann eins zu viele, wenn ein Datensatz aus Tabelle A mit einem oder mehreren Datensätzen in Tabelle B verknüpft ist. Ein Datensatz in Tabelle B kann jedoch nicht mit mehr als einem Datensatz in Tabelle A verknüpft werden.

Um eine Eins-zu-Viele-Beziehung herzustellen, muss der Primärschlüssel von Tabelle A (die "Eins" -Tabelle) der Sekundärschlüssel von Tabelle B (die "Viele" -Tabelle) sein.

Beispielsweise:

CREATE TABLE Vendor(
    VendorNumber number(4) PRIMARY KEY,
    Name varchar2(20),
    Address varchar2(20),
    City varchar2(15),
    Street varchar2(2),
    ZipCode varchar2(10),
    Contact varchar2(16),
    PhoneNumber varchar2(12),
    Status varchar2(8),
    StampDate date
);

CREATE TABLE Inventory(
    Item varchar2(6) PRIMARY KEY,
    Description varchar2(30),
    CurrentQuantity number(4) NOT NULL,
    VendorNumber number(2) REFERENCES Vendor(VendorNumber),
    ReorderQuantity number(3) NOT NULL
);

Viele zu viele (M: M)

Eine Beziehung ist genau dann viele-zu-viele, wenn ein Datensatz aus Tabelle A mit einem oder mehreren Datensätzen in Tabelle B verknüpft ist und umgekehrt.

Um eine Viele-zu-Viele-Beziehung herzustellen, erstellen Sie eine dritte Tabelle mit dem Namen "ClassStudentRelation", die die Primärschlüssel von Tabelle A und Tabelle B enthält.

CREATE TABLE Class(
    ClassID varchar2(10) PRIMARY KEY, 
    Title varchar2(30),
    Instructor varchar2(30), 
    Day varchar2(15), 
    Time varchar2(10)
);

CREATE TABLE Student(
    StudentID varchar2(15) PRIMARY KEY, 
    Name varchar2(35),
    Major varchar2(35), 
    ClassYear varchar2(10), 
    Status varchar2(10)
);  

CREATE TABLE ClassStudentRelation(
    StudentID varchar2(15) NOT NULL,
    ClassID varchar2(14) NOT NULL,
    FOREIGN KEY (StudentID) REFERENCES Student(StudentID), 
    FOREIGN KEY (ClassID) REFERENCES Class(ClassID),
    UNIQUE (StudentID, ClassID)
);
Arabinda Banik
quelle
1. Beispiel: GID-Nummer (6) und SGID-Nummer (4), warum? Sollte SGID nicht auch (6) sein? Und am 2. Beispiel Nummer (4) und Nummer (2) ...
obeliksz
@obeliksz könnte Nullen sein?
Moo Kuh
Warum sollten Sie UNIQUE (StudentID, ClassID) am Ende von M: N verwenden?
Strix25
1
@ strix25 Um zu vermeiden, dass Wiederholungen beim mehrmaligen Erstellen derselben ClassStudentRelation-Zeile vermieden werden. Wenn Sie nicht sicherstellen, dass beide Fremdschlüssel StudentID und ClassID eindeutig sind, was hört dann auf, eine neue Zeile mit derselben StudentID und ClassID zu erstellen? da sie im obigen Code nicht eindeutig sind. Sie implementieren es also entweder wie den obigen Code oder fügen einen Primärschlüssel hinzu, der sowohl StudentID als auch ClassID enthält, um zu vermeiden, dass wiederholt dieselbe Zeile in ClassStudentRelation erstellt wird.
Fouad Boukredine
1
@valik Daten in Datenbanken verweisen auf vorhandene Daten und erstellen nicht mehrmals dasselbe Datenelement. Warum sollten Sie das tun? Natürlich müssen Sie nicht, sonst ist es nicht effizient. In diesem Sinne kehren wir zu Ihrem Beispiel zurück (James hat Biologie und Biologie hat James). Natürlich können Sie das, ABER ohne weitere Daten zu erstellen, die bereits in der Datenbank vorhanden sind. Alles, was Sie tun müssen, ist, nur auf die bereits vorhandene zu verweisen, wenn Sie eine Beziehung erstellen möchten. Ich hoffe das hilft :)
Fouad Boukredine
8

Dies ist eine sehr häufige Frage, daher habe ich beschlossen, diese Antwort in einen Artikel umzuwandeln .

Eins zu viele

Die Eins-zu-Viele-Tabellenbeziehung sieht wie folgt aus:

Eins zu viele

In einem relationalen Datenbanksystem verknüpft eine Eins-zu-Viele-Tabellenbeziehung zwei Tabellen basierend auf einer Foreign KeySpalte im untergeordneten Element, die Primary Keyauf die der übergeordneten Tabellenzeile verweist .

Im obigen Tabellendiagramm hat die post_idSpalte in der post_commentTabelle eine Foreign KeyBeziehung zur Spalte mit der postTabellen-ID Primary Key:

ALTER TABLE
    post_comment
ADD CONSTRAINT
    fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post

Eins zu eins

Die Eins-zu-Eins-Tabellenbeziehung sieht wie folgt aus:

Eins zu eins

In einem relationalen Datenbanksystem verknüpft eine Eins-zu-Eins-Tabellenbeziehung zwei Tabellen basierend auf einer Primary KeySpalte im untergeordneten Foreign KeyElement, die auch Primary Keyauf die übergeordnete Tabellenzeile verweist .

Daher können wir sagen, dass die untergeordnete Tabelle die Primary Keymit der übergeordneten Tabelle teilt .

Im obigen Tabellendiagramm hat die idSpalte in der post_detailsTabelle auch eine Foreign KeyBeziehung zur postTabellenspalte id Primary Key:

ALTER TABLE
    post_details
ADD CONSTRAINT
    fk_post_details_id
FOREIGN KEY (id) REFERENCES post

Viel zu viel

Die Viele-zu-Viele-Tabellenbeziehung sieht wie folgt aus:

Viel zu viel

In einem relationalen Datenbanksystem verknüpft eine Viele-zu-Viele-Tabellenbeziehung zwei übergeordnete Tabellen über eine untergeordnete Tabelle, die zwei Foreign KeySpalten enthält , die auf die Primary KeySpalten der beiden übergeordneten Tabellen verweisen .

Im obigen Tabellendiagramm hat die post_idSpalte in der post_tagTabelle auch eine Foreign KeyBeziehung zur postTabellen-ID- Primary KeySpalte:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_post_id
FOREIGN KEY (post_id) REFERENCES post

Die tag_idSpalte in der post_tagTabelle hat eine Foreign KeyBeziehung zur Spalte mit der tagTabellen-ID Primary Key:

ALTER TABLE
    post_tag
ADD CONSTRAINT
    fk_post_tag_tag_id
FOREIGN KEY (tag_id) REFERENCES tag
Vlad Mihalcea
quelle
3

Eins-zu-eins-Beziehung (1-1): Dies ist die Beziehung zwischen Primär- und Fremdschlüssel (Primärschlüssel für Fremdschlüssel nur ein Datensatz). Dies ist eine Eins-zu-Eins-Beziehung.

Eins-zu-viele-Beziehung (1-M): Dies ist auch die Beziehung zwischen Primär- und Fremdschlüsselbeziehungen, hier jedoch Primärschlüssel, der sich auf mehrere Datensätze bezieht (dh Tabelle A enthält Buchinformationen und Tabelle B enthält mehrere Herausgeber eines Buches).

Viele zu viele (MM): Viele zu viele enthalten zwei Dimensionen, die im Folgenden anhand eines Beispiels ausführlich erläutert werden.

-- This table will hold our phone calls.
CREATE TABLE dbo.PhoneCalls
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CallTime DATETIME NOT NULL DEFAULT GETDATE(),
   CallerPhoneNumber CHAR(10) NOT NULL
)
-- This table will hold our "tickets" (or cases).
CREATE TABLE dbo.Tickets
(
   ID INT IDENTITY(1, 1) NOT NULL,
   CreatedTime DATETIME NOT NULL DEFAULT GETDATE(),
   Subject VARCHAR(250) NOT NULL,
   Notes VARCHAR(8000) NOT NULL,
   Completed BIT NOT NULL DEFAULT 0
)
-- This table will link a phone call with a ticket.
CREATE TABLE dbo.PhoneCalls_Tickets
(
   PhoneCallID INT NOT NULL,
   TicketID INT NOT NULL
)
Anjan Kant
quelle
8
Wäre besser und klarer gewesen, wenn Sie auch Einschränkungen für Primärschlüssel und Fremdschlüssel hinzugefügt hätten.
Ashish K Gupta