Wie vermeide ich eine zyklische Abhängigkeit (Zirkelreferenz) zwischen 3 Tabellen?


10

Ich habe 3 Tische:

  • Menschen
  • Post
  • Likes

Wenn ich das ER-Modell entwerfe, hat es eine zyklische Abhängigkeit:

         1: N.
Leute -------- <Post

         1: N.
Beitrag ---------- <Gefällt mir

         1: N.
Leute -------- <Mag

Die Logik lautet:

  • 1 Personen können viele Beiträge haben.

  • 1 Beitrag hat viele Likes.

  • 1 Person kann viele Beiträge mögen (erstellte Person kann ihren eigenen Beitrag nicht mögen).

Wie kann ich diese Art von zyklischem Design entfernen? Oder ist mein DB-Design falsch?

Antworten:


10

Geschäftsregeln

Lassen Sie uns die von Ihnen vorgelegten Geschäftsregeln umformulieren:

  • A Personerzeugt null, eins oder viele Posts .
  • A Posterhält null, eins oder viele Likes .
  • A Personmanifestiert Null-Eins-oder-Viele Likes , von denen jedes zu einem bestimmten gehört Post .

Logische Modelle

Dann habe ich aus solchen Aussagen die beiden in Abbildung 1 gezeigten IDEF1X [1] -Datenmodelle auf logischer Ebene abgeleitet .

Abbildung 1 - Datenmodelle für Personen und Beiträge

Option A.

Wie Sie im Modell der Option A sehen können, wird [2] als AUSLÄNDISCHER SCHLÜSSEL (FK) von nach PersonId migriert , erhält jedoch den Rollennamen [3] von und dieses Attribut bildet zusammen mit dem PRIMÄREN SCHLÜSSEL (PK) des Entitätstyps.PersonPostAuthorIdPostNumberPost

Ich gehe davon aus, dass a Likenur in Verbindung mit einem bestimmten existieren kann Post, also habe ich eine LikePK eingerichtet, die aus drei verschiedenen Attributen besteht : PostAuthorId, PostNumberund LikerId. Die Kombination von PostAuthorIdund PostNumberist eine FK, die den richtigen Bezug zur PostPK herstellt. LikerIdist wiederum eine FK, die die geeignete Assoziation mit herstellt Person.PersonId.

Mit Hilfe dieser Struktur stellen Sie sicher, dass eine bestimmte Person nur ein einziges LikeVorkommen für dieselbe PostInstanz manifestieren kann .

Methoden, um zu verhindern, dass ein Post-Autor seinen eigenen Post mag

Da Sie nicht zulassen möchten, dass eine Person ihre verfassten Beiträge in der Implementierungsphase mögen kann, sollten Sie eine Methode festlegen, die den Wert von Like.PostAuthorIdmit dem Wert von Like.LikerIdbei jedem INSERT-Versuch vergleicht. Wenn diese Werte übereinstimmen, (a) lehnen Sie die Einfügung ab, wenn sie nicht übereinstimmen, (b) lassen Sie den Vorgang fortsetzen.

Um diese Aufgabe in Ihrer Datenbank auszuführen, können Sie Folgendes verwenden:

  1. Eine PRÜFBESCHRÄNKUNG, aber diese Methode schließt natürlich MySQL aus, da sie bisher nicht auf dieser Plattform implementiert wurde, wie Sie hier und hier sehen können .

  2. Codezeilen innerhalb einer ACID-Transaktion .

  3. Codezeilen innerhalb eines TRIGGER , die eine benutzerdefinierte Nachricht , welche die Regelverletzung Versuch zurückkehren konnte.

Option B.

Wenn der Autor kein Attribut ist, das einen Beitrag in Ihrer Geschäftsdomäne primär identifiziert, können Sie eine ähnliche Struktur wie in Option B verwenden.

Dieser Ansatz stellt auch sicher, dass ein Beitrag nur einmal von derselben Person gemocht werden kann.


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 .

2. IDEF1X definiert die Schlüsselmigration als "Modellierungsprozess zum Platzieren des Primärschlüssels einer übergeordneten oder generischen Entität in ihrer untergeordneten oder Kategorieentität als Fremdschlüssel".

3. Ein Rollenname ist eine Bezeichnung, die einem Fremdschlüsselattribut zugewiesen wird, um die Bedeutung dieses Attributs im Kontext seines entsprechenden Entitätstyps auszudrücken. Die Benennung von Rollen wird seit 1970 von Dr. EF Codd in seinem wegweisenden Artikel mit dem Titel „Ein relationales Datenmodell für große gemeinsam genutzte Datenbanken“ empfohlen . IDEF1X - die Treue zu relationalen Praktiken zu wahren - befürwortet dieses Verfahren ebenfalls.


6

Ich sehe hier nichts Zyklisches. Es gibt Personen und Stellen und zwei unabhängige Beziehungen zwischen diesen Entitäten. Ich würde Likes als die Implementierung einer dieser Beziehungen sehen.

  • Eine Person kann viele Beiträge schreiben, ein Beitrag wird von einer Person geschrieben: 1:n
  • Eine Person kann viele Beiträge mögen, ein Beitrag kann vielen Menschen gefallen: n:m
    Die n: m-Beziehung kann mit einer anderen Beziehung implementiert werden : likes.

Grundlegende Implementierung

Die grundlegende Implementierung könnte in PostgreSQL folgendermaßen aussehen :

CREATE TABLE person (
  person_id serial PRIMARY KEY
, person    text NOT NULL
);

CREATE TABLE post (
  post_id   serial PRIMARY KEY
, author_id int NOT NULL  -- cannot be anonymous
     REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE  -- 1:n relationship
, post      text NOT NULL
);

CREATE TABLE likes (  -- n:m relationship
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int REFERENCES post ON UPDATE CASCADE ON DELETE CASCADE
, PRIMARY KEY (post_id, person_id)
);

Insbesondere ist zu beachten , dass ein Beitrag muss einen Autor hat ( NOT NULL), während die Existenz von Gleichen sind optional. Für bestehende mag jedoch postund person muss sowohl durch die referenzierte (erzwungen werden , PRIMARY KEYdie beide Spalten macht NOT NULLautomatisch (Sie könnten diese Einschränkungen ausdrücklich hinzufügen, redundant) so anonym Gleichen sind auch unmöglich.

Details zur n: m-Implementierung:

Verhindern Sie selbstähnlich

Sie haben auch geschrieben:

(Erstellte Person kann ihren eigenen Beitrag nicht mögen).

Dies ist in der obigen Implementierung noch nicht erzwungen. Sie könnten einen Auslöser verwenden .
Oder eine dieser schnelleren / zuverlässigeren Lösungen:

Für einen Preis absolut solide

Wenn es sein muss rock-solid , könnten Sie den FK erstrecken sich von likesbis postzu den sind author_idredundant. Dann können Sie Inzest mit einer einfachen CHECKEinschränkung ausschließen.

CREATE TABLE likes (
  person_id int REFERENCES person ON UPDATE CASCADE ON DELETE CASCADE
, post_id   int 
, author_id int NOT NULL
, CONSTRAINT likes_pkey PRIMARY KEY (post_id, person_id)
, CONSTRAINT likes_post_fkey FOREIGN KEY (author_id, post_id)
     REFERENCES post(author_id, post_id) ON UPDATE CASCADE ON DELETE CASCADE
, CONSTRAINT no_self_like CHECK (person_id <> author_id)
);

Dies erfordert eine ansonsten auch redundante UNIQUEEinschränkung in post:

ALTER TABLE post ADD CONSTRAINT post_for_fk_uni UNIQUE (author_id, post_id);

Ich habe author_idzuerst einen nützlichen Index geliefert, während ich dabei bin.

Verwandte Antwort mit mehr:

Billiger mit einer CHECKEinschränkung

Aufbauend auf der obigen "Basisimplementierung".

CHECKEinschränkungen sollen unveränderlich sein. Das Verweisen auf andere Tabellen zur Überprüfung ist niemals unveränderlich. Wir missbrauchen das Konzept hier ein wenig. Ich schlage vor, die Einschränkung zu deklarieren, NOT VALIDum dies angemessen widerzuspiegeln. Einzelheiten:

Eine CHECKEinschränkung erscheint in diesem speziellen Fall vernünftig, da der Autor eines Beitrags wie ein Attribut erscheint, das sich nie ändert. Aktualisierungen für dieses Feld sind nicht zulässig, um sicherzugehen.

Wir fälschen eine IMMUTABLEFunktion:

CREATE OR REPLACE FUNCTION f_author_id_of_post(_post_id int)
  RETURNS int AS
'SELECT p.author_id FROM public.post p WHERE p.post_id = $1'
LANGUAGE sql IMMUTABLE;

Ersetzen Sie 'public' durch das tatsächliche Schema Ihrer Tabellen.
Verwenden Sie diese Funktion in einer CHECKEinschränkung:

ALTER TABLE likes ADD CONSTRAINT no_self_like_chk
   CHECK (f_author_id_of_post(post_id) <> person_id) NOT VALID;

4

Ich denke, Sie haben Schwierigkeiten, dies herauszufinden, weil Sie Ihre Geschäftsregeln angeben.

Personen und Beiträge sind "Objekte". Wie ist ein Verb.

Sie haben wirklich nur 2 Aktionen:

  1. Eine Person kann einen oder mehrere Beiträge erstellen
  2. Viele Personen können viele Beiträge mögen. (eine Zusammenstellung Ihrer letzten 2 Aussagen)

Leute mögen Beiträge Diagramm

Die Tabelle "Gefällt mir" enthält person_id und post_id als Primärschlüssel.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.