SQL2005: Eine Tabelle mit mehreren Tabellen verknüpfen und Ref Integrity beibehalten?


3

Hier ist eine Vereinfachung meiner Datenbank:

Table: Property 
Fields: ID, Address 

Table: Quote 
Fields: ID, PropertyID, BespokeQuoteFields... 

Table: Job 
Fields: ID, PropertyID, BespokeJobFields...

Dann haben wir andere Tabellen, die und Job Tabellen individuell auf die Quote beziehen.

Ich muss jetzt eine Nachricht Tabelle hinzufügen, wo Benutzer Telefonnachrichten aufzeichnen können, die von Kunden in Bezug auf Jobs und Angebote hinterlassen wurden.

konnte ich zwei identische Tabellen erstellen (QuoteMessage und JobMessage), aber dies verstößt gegen das DRY Haupt und scheint chaotisch.

Table: Message 
Fields: ID, RelationID, RelationType, OtherFields...

Aber das hält mich Einschränkungen verwenden, meine referenzielle Integrität zu erzwingen:

konnte ich eine Nachricht Tabelle erstellen. Ich kann auch sehen, dass es Probleme mit der Entwicklungsseite verursacht, die später Linq zu SQL verwendet.

Gibt es eine elegante Lösung für dieses Problem, oder muss ich letztendlich etwas zusammenhacken?

Verbrennungen

4

Erstellen einer Nachricht Tabelle, eine einzigartige Meldungs ​​und die verschiedenen Eigenschaften, die Sie für eine Nachricht speichern, müssen enthält.

Table: Message 
Fields: Id, TimeReceived, MessageDetails, WhateverElse... 

Erstellen Sie zwei Verknüpfungstabellen - QuoteMessage und JobMessage. Diese enthalten jeweils nur zwei Felder, Fremdschlüssel für das Angebot/den Job und die Nachricht.

Table: QuoteMessage 
Fields: QuoteId, MessageId 

Table: JobMessage 
Fields: JobId, MessageId 

Auf diese Weise können die Daten Eigenschaften einer Nachricht an einem Ort nur definiert haben (so dass es leicht, zu erweitern und über alle Nachrichten abzufragen), aber Sie haben auch die referentielle Integrität Zitate und Jobs Links zu eine beliebige Anzahl von Nachrichten. Tatsächlich könnten sowohl ein Angebot als auch ein Auftrag mit der Nachricht gleich verknüpft werden (ich bin mir nicht sicher, ob das für Ihr Geschäftsmodell geeignet ist, aber zumindest das Datenmodell gibt Ihnen die Option).


1

Über die einzige andere Möglichkeit, die ich denken kann, ist eine Basis-Nachrichtentabelle, mit einer ID und einer TypeId. Ihre Untertabellen (QuoteMessage und JobMessage) verweisen dann sowohl auf MessageId als auch auf TypeId auf die Basistabelle. Sie verfügen jedoch auch über CHECK CONSTRAINTS, um nur die entsprechende MessageTypeId zu erzwingen.

Table: Message 
Fields: Id, MessageTypeId, Text, ... 
Primary Key: Id, MessageTypeId 
Unique: Id 

Table: MessageType 
Fields: Id, Name 
Values: 1, "Quote" : 2, "Job" 

Table: QuoteMessage 
Fields: Id, MessageId, MessageTypeId, QuoteId 
Constraints: MessageTypeId = 1 
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId) 
      QuoteId = Quote.QuoteId 

Table: JobMessage 
Fields: Id, MessageId, MessageTypeId, JobId 
Constraints: MessageTypeId = 2 
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId) 
      JobId = Job.QuoteId 

Was kostet Sie das, verglichen mit nur einer JobMesssage- und einer QuoteMessage-Tabelle? Es erhöht eine Nachricht zu einem Bürger erster Klasse, so dass Sie alle Nachrichten aus einer einzigen Tabelle lesen können. Im Gegenzug wird Ihr Anfragepfad von einer Nachricht zu seinem relevanten Angebot oder Job 1 weitere mitmachen. Es hängt irgendwie von Ihrem App-Flow ab, ob das ein guter Kompromiss ist oder nicht.

Wie für zwei identische Tabellen, die DRY verletzen - ich würde nicht auf diese hängen. Im DB-Design geht es weniger um DRY und mehr um Normalisierung. Wenn die 2 Dinge, die Sie modellieren, die gleichen Attribute (Spalten) haben, aber tatsächlich verschiedene Dinge (Tabellen) sind - dann ist es sinnvoll, mehrere Tabellen mit ähnlichen Schemas zu haben.Viel besser als die Umkehrung von verschiedenen Dingen zusammen.


1

@burns

Ians Antwort (1) richtig [siehe Anmerkung]. Verwenden Sie eine viele zu viele Tabelle QUOTEMESSAGE zu verbinden QUOTE zu MESSAGE ist das korrekteste Modell, aber verwaiste MESSAGE Datensätze verlassen.

Dies ist einer dieser seltenen Fälle Fälle, in denen ein Trigger verwendet werden kann. Es muss jedoch Vorsicht angewendet werden, um sicherzustellen, dass der einzelne Datensatz MESSAGE nicht mit QUOTE und JOB verknüpft werden kann.

create trigger quotemessage_trg 
on quotemessage 
for delete 
as 
begin 

delete 
from [message] 
where [message].[msg_id] in 
    (select [msg_id] from Deleted); 

end 

Hinweis zu Ian, ich glaube, es ein Tippfehler in der Tabellendefinition ist für JobMessage, wo die Säulen JobId, MessageId sein sollen (?). Ich würde Ihr Angebot bearbeiten, aber es könnte einige Jahre dauern, bis ich dieses Ansehen erlangt habe!


0

Warum haben Sie nicht beide Felder QuoteId und JobId in der Nachrichtentabelle? Oder muss eine Nachricht entweder ein Zitat oder einen Job betreffen und nicht beides?