Beratung zu einem grundlegenden Design, erstmaligem Datenbankdesign

8

Ich nehme an einem Kurs teil, um Java-Entwickler zu werden.

Der Kurs beinhaltet die Verwendung von Datenbanken, aber wir entwerfen leider nie wirklich welche.

Meistens erhalten wir vorgefertigte Datenbanken und müssen Code darauf implementieren, um Daten einzufügen, zu aktualisieren, zu lesen oder zu löschen.

Aber wenn mein letzter Test kommt, werde ich wahrscheinlich etwas machen, das eine Datenbank beinhaltet, und deshalb möchte ich versuchen, ein paar kleinere zu entwerfen, um den Dreh raus zu bekommen, da ich festgestellt habe, dass ein gutes Datenbankdesign einen großen Unterschied macht, wenn Schreiben Sie den Code, um damit zu arbeiten.

Ich hoffe, dass diese Art von Fragen hier erlaubt sind und dass sie nicht zu weit gefasst werden.


Dies ist ein kleines Design, das ich für etwas Einfaches wie clubsund membersmit addressesund gemacht habe phonenumbers.

  • Es wird mehrere Clubs geben.
  • Jeder Club hat mehrere Mitglieder (offensichtlich)
  • Ein Mitglied kann nicht Mitglied mehrerer Clubs sein
  • Ein Mitglied kann mehrere Telefonnummern und E-Mail-Adressen haben
  • Ein Mitglied kann nur eine Adresse haben
  • Eine Adresse kann verschiedenen Mitgliedern (Paaren oder Geschwistern) gehören.

Meine größten Verwirrungen:

  • Wenn ich eine Spalte hinzufügen möchte Club, die den Eigentümer beschreibt, der auch Mitglied sein wird, was ist der beste Ansatz, ohne dass dasselbe Mitglied zweimal aufgeführt wird?

  • Sollte ich alle meine Tabellen auf das automatische Inkrementieren einer ID setzen oder wäre dies eine schlechte Idee? (Vor- / Nachteile?)

  • Wenn ich auf der Registerkarte Fremdschlüssel Fremdschlüssel hinzufüge, entsprechen diese automatisch der richtigen Tabelle oder muss ich diese auch zu den Spalten hinzufügen? (siehe Bild 2)

  • Und meine wahrscheinlich noobiest Frage überhaupt ... Platziere ich die Fremdschlüssel von phonenumberund emailin ihrer jeweiligen Tabelle, die mit einer person_Id verknüpft sind, oder sollte ich phoneNumber und E-Mail-IDs in die person-Tabelle einfügen?

(Ich entschuldige mich dafür, dass die Sprache auf den Bildern nicht Englisch ist. Ich hoffe, das ist kein allzu großes Problem.)

Design

Fremde Schlüssel

Vahx
quelle

Antworten:

11

Antworten auf Ihre individuellen Fragen

Wenn ich eine Spalte hinzufügen möchte Club, die den Eigentümer beschreibt, der auch Mitglied sein wird, was ist der beste Ansatz, ohne dass dasselbe Mitglied zweimal aufgeführt wird?

Wenn Sie - wie in Ihren Spezifikationen angegeben a Person can be a Member of only one Club- daran interessiert sind, dieses Datum einfach als wahr oder falsch zu speichern , können Sie der Tabelle eine BIT(1)oder eine BOOLEAN( TINYINT) -Spalte hinzufügen Person, und Sie möchten diese Spalte möglicherweise aufrufen IsClubOwner. Auf diese Weise können Sie die Tatsache registrieren , dass eine bestimmte Person ist ein Clubbesitzer ausschließlich einmal. Abgesehen davon , dass diese Methode ermöglicht es auch die Möglichkeit der Beibehaltung mehr Personen als Inhaber des gleichen Club Auftreten. Sie können eine logische Darstellung dieses Ansatzes in Abbildung 1 sehen .

Sie suchen jedoch nach dem besten Ansatz, und meiner Erfahrung nach beinhaltet ein solcher Ansatz die Entwicklung einer viel erweiterbareren und vielseitigeren Struktur. Befolgen Sie in diesem Zusammenhang den Verlauf einer Modellierungsübung für diese und andere Punkte in den Abschnitten "Abdecken Ihrer verbleibenden Spezifikationen", "Person als Mitglied mehrerer Clubs" und "Mitglied und Eigentümer als separate Entitätstypen".

Sollte ich alle meine Tabellen automatisch inkrementieren idoder wäre dies eine schlechte Idee? (Vorteile / Nachteile?)

Wenn Sie einer expliziten Anforderung gegenüberstehen, die die Definition einer Tabelle mit einer Spalte mit solchen Merkmalen angibt und diese Spalte eine gültige Kontextbedeutung hat oder einem bestimmten Zweck dient, z. B. als Ersatz für einen breiten natürlichen PRIMARY KEY (PK), dann ja, Sie sollten so vorgehen.

Andernfalls halte ich es für unnötig , wenn Sie diese Anforderung nicht angegeben haben, da Sie eine bedeutungslose zusätzliche Spalte und (möglicherweise?) Auch einen zusätzlichen INDEX in Ihrer Datenbank speichern und verwalten müssen .

Wie üblich müssen Sie jeden Fall zusammen mit seinen allgemeinen Auswirkungen analysieren, um zu entscheiden, wie Sie fortfahren möchten.

Wenn ich auf der Registerkarte Fremdschlüssel Fremdschlüssel hinzufüge, entsprechen diese automatisch der richtigen Tabelle oder muss ich diese auch zu den Spalten hinzufügen?

In diesem Zusammenhang rate ich Ihnen, Ihre Datenbankstruktur manuell zu erstellen und Ihre eigenen DDLAnweisungen zu codieren , bis Sie das Thema richtig verstanden haben. Wenn Sie dies tun, können Sie die Prozesse, die grafische Tools „unter der Haube“ ausführen, leichter verstehen.

Für mich zum Beispiel, eine Aussage wie die folgende zu erstellen:

CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)

Ist viel lehrreicher als die Verwendung von GUI-Tools, um diese Art von Aufgaben auszuführen, insbesondere jetzt, wo Sie Ihre ersten Entwürfe erstellen.

Und meine wahrscheinlich noobiest Frage von allen ... Platziere ich die Fremdschlüssel von phone_numberund emailin ihrer jeweiligen Tabelle, die mit einem verknüpft sind, person_idoder sollte ich phone_numberund email idsin die Personentabelle setzen?

Persönlich denke ich, dass diese und alle Ihre anderen Fragen vollständig gültig und gut kontextualisiert sind .

Um auf die technischen Aspekte zurückzukommen, die uns betreffen, bietet diese genaue Untersuchung eine gute Gelegenheit, die beiden folgenden Behauptungen zu überprüfen:

  • A Person can be reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber can be used to reach one-to-many People

So kann man schließen , dass es eine viele-zu-viele - Beziehung zwischen Personund PhoneNumberdeshalb schlage ich vor , die Schaffung eines assoziativen Tabelle namens PersonPhoneNumberauf die Beziehung in der Datenbank zu repräsentieren. Die PK dieser Tabelle sollte aus zwei verschiedenen Spalten bestehen: PersonId(ein AUSLÄNDISCHER SCHLÜSSEL [FK], auf den verwiesen wird Person.PersonId) und PhoneNumber(ein FK, auf den verwiesen wird PhoneNumber.Number). Eine Beschreibung aller oben genannten Punkte auf logischer Ebene finden Sie in Abbildung 1 .

Lassen Sie uns andererseits die beiden folgenden Sätze untersuchen:

  • A Person can be contacted via zero-one-or-many EmailAddresses
  • An EmailAddress can be used to contact exactly one Person

Dann sollten Sie eine FK-Referenzierung in Personder EmailAddressTabelle festlegen , und diese Tabelle sollte auch eine zusammengesetzte PK enthalten, die aus den Spalten PersonIdund besteht Address. Auf diese Weise können Sie sicherstellen, dass dieselbe Kombination von EmailAddress.PersonIdund EmailAddress.Addressnur einmal eingefügt werden kann.

Wenn Sie auch sicherstellen möchten, dass eine bestimmte EmailAddres.AddressZeile in einer einzigen Zeile gespeichert werden kann, müssen Sie nur eine EINZIGARTIGE BESCHRÄNKUNG für diese Spalte festlegen .

Vorgeschlagene logische Datenmodelle

Um meine Vorschläge klarer darzustellen , habe ich vier verschiedene logische IDEF1X [1] -Modelle aufgenommen, die in Abbildung 1 , Abbildung 2 , Abbildung 3 und Abbildung 4 dargestellt sind . In den entsprechenden Abschnitten werde ich die wichtigsten Funktionen erläutern, die in den einzelnen Funktionen angezeigt werden. Sie können auch ein PDF von Dropbox herunterladen, das die meisten der diskutierten Elemente in ein einziges Modell integriert.

Deckt Ihre verbleibenden Spezifikationen ab

Personen und Adressen in Beziehung setzen

Lassen Sie uns die beiden folgenden (leicht umformulierten) Aussagen untersuchen, die für Personen und Adressen relevant sind :

  • A Person can only have one Address
  • An Address can belong to different People (couples or siblings)

Um diese Einschränkungen zu umgehen, können Sie ein Datenmodell implementieren, das dem in Abbildung 1 gezeigten ähnelt .

Abb. 1. Datenmodell für Clubs und Mitglieder - Erste Spezifikationen

Unter Berücksichtigung des angegebenen Modells sollten Sie die folgenden Schritte ausführen:

  1. Erstellen Sie eine Tabelle mit dem Namen PersonAddressFixieren einer Beziehung zwischen Personund Address. Legen Sie die Spalten PersonIdund AddressIdals zusammengesetzte PK dieser Tabelle fest.

  2. Konfigurieren Sie eine EINZIGARTIGE EINSCHRÄNKUNG für die PersonAddress.PersonIdSpalte, um sicherzustellen, dass ein bestimmter Wert in höchstens eine Zeile der Tabelle eingefügt werden kann. Auf der logischen Ebene impliziert dieser Umstand, dass er PersonAddress.PersonIdzu einem ALTERNATIVEN SCHLÜSSEL geworden ist [2] .

  3. Wenn der Wert von AddressIdin einem bestimmten PersonAddressEinfügeversuch noch nicht gespeichert wurde, lassen Sie die Einfügung fortgesetzt werden. Wenn dieser Wert bereits in einer Zeile vorhanden ist, müssen Sie überprüfen, ob (a) PersonIdderjenige, der sich registriert hat, AddressIdauch als registriert ist Marriage.WifeIdWenn das PersonIdein Mann ist (Datum abgeleitet über das Person.GenreCode) oder (b), PersonIdist das das, Marriage.HusbandIdwenn das PersonIdeine Frau ist (abgeleitet auch aufgrund von Person.GenreCode). Wenn eine dieser Bedingungen in der entsprechenden Situation erfüllt ist, sollten Sie das INSERT fortsetzen.

  4. Wenn die oben genannten Bedingungen nicht erfüllt sind, besteht immer noch die Möglichkeit, dass ein PersonAddressEinfügungsversuch erfolgreich ist. Sie müssen überprüfen, ob der PersonIdWert, der an dem Einfügungsversuch beteiligt ist, mindestens einen Progeny.ParentIdmit dem Wert teilt PersonId, der den bereits registriert hat PersonAddress.AddressId. Wenn diese Bedingung erfüllt ist, dann bedeutet es , dass sie gespeichert wie Siblingsin der Datenbank, so dass diese INSERT gelingen muss.

Wie bei jeder Implementierung einer relationalen Datenbank sollten Sie ernsthaft in Betracht ziehen, Ihre DMLVorgänge in ACID-Transaktionen auszuführen , damit Sie die Integrität und Konsistenz der Daten, mit denen Sie arbeiten, schützen können .

Beachten Sie die Anforderungen, die Sie in den Kommentaren hinzugefügt haben: Adressen und Telefonnummern, die Clubs und Personen gleichermaßen dienen

Unter der Bedingung, dass Sie Adressen und Telefonnummern die Möglichkeit geben möchten, sowohl Personen als auch Clubs zu bedienen , können Sie eine Supertyp-Subtyp-Beziehung verwenden . Hier ist eine Antwort, in der ich diese Art von Strukturen detaillierter behandle, falls Sie interessiert sind.

Im vorliegenden Szenario könnten Sie einen Begriff definieren Personund Clubals Untertypen einer neuen benannten Entität Partyeinen Begriff verwenden, der in Rechtskreisen häufig verwendet wird, um für (a) eine Person oder (b) eine Gruppe von Personen zu stehen (wie in Sinn Nr. 6 angegeben ). Bei dieser Methode werden die Beziehungen zwischen Addresses(oder PhoneNumbers) und Peopleund Clubsdurch Partyden Supertyp definiert. In Abbildung 2 ist dieser Vorschlag dargestellt.

Abb. 2. Datenmodell für Clubs und Mitglieder - Zweite Spezifikation

Party und Adresse

So können wir in diesem neuen Modell lesen, dass:

  • A Party keeps zero-one-or-many Addresses
  • An Address is kept by one-to-many Parties

Somit gibt es eine viele-zu-viele - Beziehung beteiligt Partyund Addressdas ist durch die zum Ausdruck gebracht PartyAddressEinheit.

Party und Telefonnummer

Darüber hinaus können wir das interpretieren:

  • A Party is reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber is used by one-to-many Parties

Aus diesem Grund habe ich die PartyPhoneNumberEntität hinzugefügt , die die Viele-zu-Viele-Zuordnung beschreibt, die zwischen den Entitätstypen Partyund wirksam wird PhoneNumber.

Party und Club oder Person

Dann kann man auch lesen, dass:

  • A Party is either a Club or a Person

Liefert daher Partyeine Verbindung von entweder Clubs oder People nach Addresses(oder PhoneNumbers).

Person als Mitglied mehrerer Clubs

Als @aldwinaldwin mentiones in seiner Antwort, wenn Sie die Funktionalität für einen zur Verfügung stellen möchten Person ein sein Mitglied mehrerer Vereine , dann können Sie eine Tabelle enthalten genannt , ClubMemberdass als eine weitere many-to-many relaltionship handeln würde, diesmal natürlich , Verbinden Personund Club.

Ich möchte dem oben Gesagten hinzufügen, dass diese Tabelle auch nützlich sein kann, um eine konkrete Person als Eigentümer mehrerer Clubs zu speichern , indem die bereits erwähnte IsClubOwnerboolesche Spalte eingefügt wird. In der Tat kann man sagen, dass diese neue Tabelle die Darstellung eines eigenständigen integralen Entitätstyps ist.

Wie in gezeigt , Figur 3 erfordert eine solche Tabelle , die eine Verbund PK der Spalten aus ClubIdund MemberId(einen Rollennamen [3] gegeben PersonId), und diese Spalten auch als FKs zeigt, entsprechend festgelegt werden, zu Clubund Person.

Abb. 3. Datenmodell für Clubs und Mitglieder - Person als Mitglied mehrerer Clubs

Eine anpassungsfähigere Struktur

Mit dieser Einstellung können Sie auch die ursprüngliche Regel einhalten, die dies besagt. a Person can be a member of only one ClubSie müssen der MemberIdSpalte jedoch nur eine EINZIGARTIGE BESCHRÄNKUNG hinzufügen , damit ein bestimmter Wert nur einmal eingegeben werden kann. Wie Sie feststellen können, ist diese Struktur viel anpassungsfähiger als die in Abbildung 1 gezeigte , da Sie durch Löschen der EINZIGARTIGEN EINSCHRÄNKUNG (oder des INDEX) die oben genannte Funktionalität öffnen würden, die es einer Person ermöglicht, Mitglied verschiedener Clubs bei der zu werden gleiche Zeit.

Mitglied und Eigentümer als separate Entitätstypen

Wie Sie wissen, kann die Aufbewahrung mehrerer Fakten über die Rolle einer Person als Eigentümer eines Clubs - abgesehen von der bloßen Existenz eines wahren oder falschen Attributs - sehr vorteilhaft sein. Zum Beispiel können Sie das halten Zeitpunkt des Inkrafttretens , in dem eine bestimmte Person die sich Besitzer eines Club , daher können Sie diese Situation verwalten , indem eine separate Einheit Typ namens Einführung ClubOwner, wie dargestellt in Abbildung 4 .

Abb. 4. Datenmodell für Clubs und Mitglieder - Mitglied und Eigentümer als separate Entitätstypen

Sobald Sie eine Tabelle basierend auf diesem neuen Entitätstyp erstellt haben, können Sie die Anpassungsspalten hinzufügen, die die Merkmale darstellen, die ausschließlich dann ins Spiel kommen, wenn a Persondas Ownervon a ist Club. Wie dargestellt, würde diese Tabelle eine PK enthalten, die aus den FK-Spalten besteht, auf die verwiesen wird, Person.PersonIdund auf Club.ClubIddiese Weise eine beliebige Kombination von ClubOwner.OwnerId(oder ClubOwner.PersonId, wenn Sie es vorziehen) und ClubOwner.ClubIdkann in nur einer Gelegenheit eingefügt werden.

Natürlich mit dieser Konfiguration können Sie immer noch in boolean Form ableiten , wenn ein Persondas ist Ownereines bestimmten Clubmit Hilfe einer Abfrage , dass die Renditen einen skalaren Wert, der ausgewertet werden kann wahr oder falsch .


Anmerkungen

1. Die Integrationsdefinition für die Informationsmodellierung ( IDEF1X ) ist eine sehr empfehlenswerte Datenmodellierungstechnik , die im Dezember 1993 vom Nationalen Institut für Standards und Technologie ( NIST ) der Vereinigten Staaten als Standard definiert wurde . Es basiert fest auf (a) einigen theoretischen Arbeiten, die vom Urheber des relationalen Modells verfasst wurden , dh Dr. EF Codd ; zu (b) der von Dr. PP Chen entwickelten Entity-Relationship-Theorie ; und auch auf (c) der Logical Database Design Technique , erstellt von Robert G. Brown . Es ist erwähnenswert, dass IDEF1X warformalisiert durch Logik erster Ordnung .

2. Ein ALTERNATIVER SCHLÜSSEL ist ein Attribut (oder eine Kombination von Attributen), das Werte enthält, die ein Entitätsvorkommen eindeutig identifizieren, jedoch nicht als PK des entsprechenden Entitätstyps ausgewählt wurden. Jeder Entitätstyp kann null, einen oder mehrere ALTERNATE KEYS haben. In einem IDEF1X-Modell werden sie als "AK" plus ihrer jeweiligen Nummer angezeigt, z. B. AK1, AK2 usw. Sie werden normalerweise in einer SQL-DDL- Struktur über eine EINZIGARTIGE EINSCHRÄNKUNG (oder einen EINZIGARTIGEN INDEX ) implementiert .

3. Rollennamen sind Bezeichnungen (oder Aliase), die FK-Attributen zugewiesen werden, um die Bedeutung auszudrücken, die sie im Rahmen ihrer jeweiligen Entität haben. Ihre Verwendung wird seit 1970 von Dr. Codd in seinem wegweisenden Artikel mit dem Titel „Ein relationales Datenmodell für große gemeinsam genutzte Datenbanken“ empfohlen . Für seinen Teil, IDEF1X -keeping Treue hinsichtlich relationalen Practices - befürwortet auch Rolle Namensgebung.

MDCCL
quelle
2
  1. Wenn ein Eigentümer immer Mitglied seines Clubs ist. Fügen Sie der Club-Tabelle die ownerId hinzu und geben Sie die personId des Mitglieds ein, das Eigentümer ist.
  2. Das automatische Inkrementieren einer ID ist gut. Sie können ein weiteres Feld 'Code' hinzufügen, dort setzen Sie den Mitgliedscode auf die Clubkarte.
  3. Sollte automatisch in Ordnung sein (denke ich)
  4. Geben Sie personId in die Telefonnummern- und E-Mail-Tabelle ein.

... Sie können nicht Mitglied mehrerer Clubs sein? Wenn Sie können, erstellen Sie eine Tabelle ClubMember mit clubId und personId. Auf diese Weise können Sie eine Person mit mehreren Clubs verbinden.

aldwinaldwin
quelle
1
Was ist, wenn ich möchte, dass mein Club eine Telefonnummer hat? gebe ich auch eine clubIdTelefonnummer ein und lasse entweder den Club oder die Person auf null setzen?
Vahx
Ich würde nicht alle Objekte "über" trennen (Normalisierung von Daten). Geben Sie einfach 1 Telefonnummer in den Clubtisch ein. Normalisierung ist gut, aber zu viel Normalisierung kann Probleme verursachen.
Aldwinaldwin
1
aber nehmen wir an, ich möchte das tun? Ich nehme die Adresse als Beispiel, das Mitglied hat eine Adresse, aber die Clubs benötigen auch eine Adresse
Vahx
1
Erstellen Sie einen Adressdatensatz und legen Sie die Adress-ID im Club ab. Da ein Club 1 Adresse hat, hat ein Mitglied 1 Adresse. Für Telefonnummern müssen Sie personId in den Telefonnummerneintrag einfügen, um 1 zu viele zu haben. ..... Sie könnten eine Tabelle personPhoneNumber (personId, phonenumberId) + table clubPhoneNumber (clubId, phonenumberId) erstellen, was sie dann zu einer Viel-Viele-Beziehung macht.
Aldwinaldwin