In der Datenbank stößt man häufig auf eine Situation, in der eine bestimmte Tabelle mit einer von mehreren übergeordneten Tabellen verknüpft werden kann. Ich habe zwei Lösungen für das Problem gesehen, aber keine ist persönlich befriedigend. Ich bin gespannt, welche anderen Muster du da draußen gesehen hast. Gibt es einen besseren Weg, dies zu tun?
Ein erfundenes Beispiel
Nehmen wir an, mein System hatAlerts
. Benachrichtigungen können für eine Vielzahl von Objekten empfangen werden - Kunden, Nachrichten und Produkte. Eine bestimmte Warnung kann nur für einen Artikel gelten. Aus welchen Gründen auch immer, Kunden, Artikel und Produkte sind schnelllebig (oder lokalisiert), sodass die erforderlichen Texte / Daten bei der Erstellung eines Alarms nicht in Alerts abgerufen werden können. Angesichts dieses Setups habe ich zwei Lösungen gesehen.
Hinweis: Die unten stehende DDL gilt für SQL Server, aber meine Frage sollte für jedes DBMS zutreffen.
Lösung 1 - Mehrere Nullable FKeys
In dieser Lösung enthält die Tabelle, die mit einer von vielen Tabellen verknüpft ist, mehrere FK-Spalten (der Kürze halber zeigt die folgende DDL die FK-Erstellung nicht an). DAS GUTE - In dieser Lösung ist es schön, dass ich Fremdschlüssel habe. Die Null-Optimalität der FKs macht es praktisch und relativ einfach, genaue Daten hinzuzufügen. DAS SCHLECHTE Abfragen ist nicht besonders gut, da es N LEFT JOINS- oder N UNION-Anweisungen erfordert , um die zugehörigen Daten abzurufen . In SQL Server schließen insbesondere die LEFT JOINS das Erstellen einer indizierten Ansicht aus.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
ProductID int null,
NewsID int null,
CustomerID int null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
ALTER TABLE Alert WITH CHECK ADD CONSTRAINT CK_OnlyOneFKAllowed
CHECK (
(ProductID is not null AND NewsID is null and CustomerID is null) OR
(ProductID is null AND NewsID is not null and CustomerID is null) OR
(ProductID is null AND NewsID is null and CustomerID is not null)
)
Lösung 2 - Eine FK in jeder
übergeordneten Tabelle In dieser Lösung hat jede übergeordnete Tabelle eine FK in der Alarmtabelle. Es erleichtert das Abrufen von Warnungen, die einem übergeordneten Element zugeordnet sind. Auf der anderen Seite gibt es keine echte Kette von Alerts, auf die verwiesen wird. Darüber hinaus ermöglicht das Datenmodell verwaiste Warnungen, bei denen eine Warnung nicht mit einem Produkt, einer Nachricht oder einem Kunden verknüpft ist. Wieder mehrere LEFT JOINs, um die Assoziation herauszufinden.
CREATE TABLE Product (
ProductID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Product Primary Key CLUSTERED (ProductID)
)
CREATE TABLE Customer (
CustomerID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_Customer Primary Key CLUSTERED (CustomerID)
)
CREATE TABLE News (
NewsID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
Name varchar(100) not null
AlertID int null,
CONSTRAINT PK_News Primary Key CLUSTERED (NewsID)
)
CREATE TABLE Alert (
AlertID int identity(1,1) not null,
CreateUTC datetime2(7) not null,
CONSTRAINT PK_Alert Primary Key CLUSTERED (AlertID)
)
Ist das nur das Leben in einer Beziehungsdatenbank? Gibt es alternative Lösungen, die für Sie zufriedenstellender sind?
quelle
Alertable
. Ist das sinnvoll?Antworten:
Ich verstehe die zweite Lösung als nicht zutreffend, da sie keine Beziehung zwischen einem (Objekt) und vielen (Alarm) bietet.
Aufgrund der strengen 3NF-Konformität bleiben Sie bei nur zwei Lösungen.
Ich würde ein geringeres Kopplungsschema entwerfen:
Oder wenn eine Integritätsbeziehung obligatorisch sein soll, entwerfe ich:
Wie auch immer...
Drei gültige Lösungen und eine weitere, die für viele (Objekte) -zu-eins (Alarm-) Beziehungen berücksichtigt werden müssen ...
Diese präsentiert, was ist die Moral?
Sie unterscheiden sich geringfügig und gewichten die folgenden Kriterien gleich:
So wählen Sie das bequemere für Sie.
quelle
Ich habe von Triggern gepflegte Join-Tabellen verwendet. Die Lösung funktioniert ziemlich gut als letzter Ausweg, wenn eine Umgestaltung der Datenbank nicht möglich oder wünschenswert ist. Die Idee ist, dass Sie eine Tabelle haben, die nur dazu da ist, die RI-Probleme zu behandeln, und alle DRI sind dagegen.
quelle