2010-10-22 9 views
5

Diese Frage ist ein paar Mal in verschiedenen Foren in meiner Suche aufgetreten, aber keine hat eine knappe Auflösung bereitgestellt.Datenbanktabellen, eine Tabelle, die mehrere nicht verwandte Tabellen referenziert

Wenn ich die folgenden Tabellen:

User 
+- id 
+- username 
+- password 

Article 
+- id 
+- title 
+- content 

und ich möchte, dass sie verbinden, um zu bestimmen, wer erstellt, welche Artikel, konnte ich einfach die Spalte hinzufügen zu Artikel user_id als zu verwenden, Referenz. Alternativ Ich füge eine Zwischentabelle zu zeigen, wer/wann/was, zum Beispiel:

User 
+- ... 

Article 
+- ... 

ChangeHistory 
+- id 
+- article_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

Nun ist dies in Ordnung, aber das System, das ich auf Bedürfnisse bin arbeiten zu viel dynamische, in diesen neuen Module können einfach eingeführt und integriert werden. So, jetzt, wenn ich eine Medien Tabelle hinzufügen muss ich die ChangeHistory zwischen Artikel und Medien mit aufzuspalten:

User 
+- ... 

Article 
+- ... 

Media 
+- id 
+- title 
+- path 

ArticleChangeHistory 
+- id 
+- article_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

MediaChangeHistory 
+- id 
+- media_id 
+- user_id 
+- type [enum(insert, update, delete)] 
+- datetime 

Das aus der Hand schnell mit der Einführung vieler Module können. Jedes Modul müsste für die Erstellung und Verwaltung seiner eigenen ChangeHistory Tabelle verantwortlich sein.

TL; DR: Welche Vorgehensweisen kann ich untersuchen, um eine Zwischentabelle zu erstellen, die Verweise auf mehrere andere nicht verwandte Tabellen erhalten kann? Ich könnte ein * record_type * -Feld hinzufügen, das den Namen der Tabelle enthält, zu der der Datensatz gehört, aber das ist hässlich. Ich würde etwas wie eine "Tabelle ID" benötigen, um auf die Tabelle zu verweisen, von der es kommt. Auf diese Weise fällt das Modell nicht auseinander, wenn Module hinzugefügt oder entfernt werden.

Irgendwelche Ideen? Vielen Dank im Voraus.

+0

Gibt es einen Grund, warum Sie eine "Tabellen-ID" für besser halten als einen "Datensatztyp"? –

Antwort

4

Nach meiner Erfahrung, wenn die Entwickler versuchen, ihr System wirklich zu machen „dynamic“ sie sind eigentlich für Probleme zu codieren versuchen, dass sie von noch nicht gedacht haben. Das ist normalerweise ein schlechter Weg. Ist es wirklich so viel zusätzliche Arbeit für ein Modul, zwei Tabellen anstelle von einem zu enthalten?

In jedem Fall, in dem ich das Muster (oder Anti-Muster?) Gesehen habe, das versucht, eine allgemeine "tut alles" -Tabelle zu machen, ist es flach auf sein Gesicht gefallen. RDBMS funktionieren am besten mit genau definierten Problembereichen. Wenn das Modul den Verlauf beibehalten muss, sollte das Modul eine Verlaufstabelle hinzufügen, die mit der Tabelle selbst verknüpft ist. Dies hat auch einen großen Vorteil darin, dass Sie im Laufe der Zeit wahrscheinlich verschiedene Arten von Informationen in der Historie aufbewahren möchten, abhängig von der Tabelle oder dem Modul, für die/das der Verlauf aufbewahrt wird. Wenn Sie eine generische Protokolltabelle haben, wird das viel schwieriger.

Wenn Sie jetzt einfach den letzten Benutzer erfassen möchten, um ein bestimmtes Element (Tabellenzeile) zu aktualisieren oder einzufügen und das in mehreren Tabellen enthalten ist, könnten Sie ein Vererbungsmuster verwenden, in dem Sie eine übergeordnete Tabelle und mehrere untergeordnete Elemente haben Tabellen. Zum Beispiel:

CREATE TABLE Audited_Items 
(
    id INT NOT NULL IDENTITY, 
    CONSTRAINT PK_Audited_Items PRIMARY KEY CLUSTERED (id) 
) 
CREATE TABLE Articles 
(
    id INT   NOT NULL, 
    [Article specific columns] 
    CONSTRAINT PK_Articles PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_Articles_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id) 
) 
CREATE TABLE Media 
(
    id INT   NOT NULL, 
    [Media specific columns] 
    CONSTRAINT PK_Media PRIMARY KEY CLUSTERED (id), 
    CONSTRAINT FK_Media_Audited_Items FOREIGN KEY (id) REFERENCES Audited_Items (id) 
) 
CREATE TABLE Audit_Trail 
(
    audited_item_id INT   NOT NULL, 
    audit_datetime  DATETIME NOT NULL, 
    user_id   INT   NOT NULL, 
    [audit columns] 
    CONSTRAINT PK_Audit_Trail PRIMARY KEY CLUSTERED (audited_item_id, audit_datetime), 
    CONSTRAINT FK_Audit_Trail_Audited_Items FOREIGN KEY (audited_item_id) REFERENCES Audited_Items (id) 
) 
+0

Vielen Dank für Ihre ausführliche Antwort Tom. Ich mag dieses Design sehr und werde es in meiner weiteren Forschung berücksichtigen. – Dan

+0

Schließen Sie die Schleife auf die Frage, danke Tom H., scheint Ihre Methode, mein Design ziemlich gut zu erfüllen. Hoffentlich müssen nur wenige Änderungen vorgenommen werden. – Dan

2

Es scheint mir, dass Sie nach einem Führer fragen, der Sie über einen verwinkelten, dornigen Pfad führt.

Ich weiß nicht, warum Sie jedes Mal eine neue Tabelle hinzufügen müssen, wenn Sie ein neues "Modul" bekommen (mir ist nicht klar, was ein Modul ist), vorausgesetzt die Module können alle mit dem gleichen Spaltenlayout beschrieben werden . Sie könnten eine Modul-Tabelle hinzufügen und dann eine ModuleId-Spalte in die Artikeltabelle einfügen.

Artikel können auch mehr als einen Autor haben, also wenn Sie das tun, benötigen Sie eine ArticleAuthors-Tabelle. Und in einigen Kreisen ist die Reihenfolge der Autoren in einem Artikel wichtig. Es ist ein Ranking der Wichtigkeit ihres Beitrags oder ihrer Wichtigkeit in diesem Bereich. Wenn dies der Fall ist, müssten Sie eine "Ordinal" -Spalte haben, um die Position des Autors widerzuspiegeln.

+0

Danke für Ihre schnelle Antwort Tim; Module repräsentieren Subsysteme eines CMS, an dem ich gerade arbeite. Mehrere Autoren eines Artikels können vom ursprünglichen Benutzer des Autors und nachfolgenden Bearbeitern des Autors dargestellt werden. Die Benutzer werden nach Ebene geordnet (ich habe der Einfachheit halber nicht viele irrelevante Felder in meinen Beispielmodellen eingeschlossen). Ich habe gehofft, eine Art "Tabellen-ID" -Lösung zu finden, die unabhängig vom Modell selbst ist ... – Dan

+1

Um ein wenig mehr zu erweitern, habe ich eine Modules-Tabelle, um Module zu registrieren und die Registrierung aufzuheben (und Config-Parameter usw. zu halten), aber ein Modul kann mehrere Tabellen haben, wie Discography mit Track und Album. Sowohl Track als auch Album benötigen individuelle ChangeHistory-Tabellen (oder Referenzen in einer gemeinsamen Zwischentabelle) und daher reicht eine einzige module_id nicht aus, um sowohl Track als auch Album zu referenzieren. – Dan

2

Ich glaube, Sie am besten mit einem einzigen ChangeHistory Tisch sein könnten aus so etwas wie folgt aussieht: (. ZB Artikel, Medien, etc ...)

 
ItemChangeHistory 
+- id 
+- changedItem_id 
+- user_id 
+- changedItemType_id 
+- type [enum(insert, update, delete)] 
+- datetime 

und dann changedItemType_id verwenden, um herauszufinden, was geändert wurde basierend auf einer itemType Tabelle. Auf diese Weise haben Sie nur eine Tabelle für alle Inhaltsänderungsverläufe, und Sie müssen keine Tabellen hinzufügen/entfernen, wenn Sie Module hinzufügen/entfernen. Sie aktualisieren einfach die Tabelle itemType.Das bedeutet natürlich, dass das Entfernen eines Moduls sorgfältig durchgeführt werden muss - Sie könnten die ItemChangeHistory Datensätze zurücklassen, die auf den Typ dieses Moduls verweisen (aber das ist unordentlich) oder alle mit dem Modul verbundenen Historien entfernen.


Jetzt erwähnen Sie ein Modul anderen Tabellen haben, so vielleicht die mit einem Submodul ID verfolgt werden müssen, auch in ItemChangeHistory verwiesen?

0

Warum nicht

ChangeHistory 
+- id 
+- content_id 
+- content_type 
+- user_id 
+- action [enum(added, updated, deleted)] 
+- datetime 
0

@Majid: Ich verstehe, dass wahrscheinlich die vernünftigste Lösung, aber ich hatte gehofft, etwas ein bisschen mehr intuitiv, etwas zu finden, die möglicherweise die Vorteile der bestehenden DB-Parameter übernehmen könnte; wie die schwer fassbare (und eindeutig nicht vorhandene) Tabellen-ID (womit ich eine Art interner Referenz meine, die die Engine, InnoDB in meinem Fall, zur Beschreibung von Tabellen verwendet)

@fusted: Ich nehme an, ich bin werde mit so etwas gehen. Ich werde weiter nach Möglichkeiten suchen.

Verwandte Themen