Wie modelliere ich die Null-oder-Eins-zu-Null-oder-Eins-Beziehung in SQL Server auf natürlichste Weise?
Es gibt eine 'Hazard'-Tabelle, in der die Gefahren auf einer Site aufgelistet sind. Es gibt eine Aufgabentabelle für Arbeiten, die an einer Site ausgeführt werden müssen. Einige Aufgaben dienen dazu, eine Gefahr zu beheben. Keine Aufgabe kann mehrere Gefahren bewältigen. Einige Gefahren haben die Aufgabe, sie zu beheben. Mit keiner Gefahr können zwei Aufgaben verbunden sein.
Das Folgende ist das Beste, was ich mir vorstellen kann:
CREATE TABLE [dbo].[Hazard](
[HazardId] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Hazard] PRIMARY KEY CLUSTERED
(
[HazardId] ASC
))
GO
ALTER TABLE [dbo].[Hazard] WITH CHECK ADD CONSTRAINT [FK_Hazard_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([TaskId])
GO
CREATE TABLE [dbo].[Task](
[TaskId] [int] IDENTITY(1,1) NOT NULL,
[HazardId] [int] NULL,
[Details] [varchar](max) NULL,
CONSTRAINT [PK_Task] PRIMARY KEY CLUSTERED
(
[TaskId] ASC
))
GO
ALTER TABLE [dbo].[Task] WITH CHECK ADD CONSTRAINT [FK_Task_Hazard] FOREIGN KEY([HazardId])
REFERENCES [dbo].[Hazard] ([HazardId])
GO
Würden Sie das anders machen? Der Grund, warum ich mit dieser Einrichtung nicht zufrieden bin, ist, dass es eine Anwendungslogik geben muss, um sicherzustellen, dass Aufgaben und Gefahren aufeinander und nicht auf andere Aufgaben und Gefahren verweisen und dass keine Aufgabe / Gefahr auf dieselbe Gefahr / Aufgabe verweist eine andere Aufgabe / Gefahr weist auf.
Gibt es einen besseren Weg?
quelle
null
.CREATE UNIQUE INDEX x ON dbo.Hazards(TaskID) WHERE TaskID IS NOT NULL;
Antworten:
Sie können Ihrer eigenen Vorstellung von einem asymmetrischen Schema folgen, indem Sie einen der Fremdschlüssel aus dem aktuellen Setup entfernen. Um die Symmetrie zu gewährleisten, können Sie beide Fremdschlüssel entfernen und eine Junction-Tabelle mit einer eindeutigen Einschränkung für jede Referenz einführen .
Es wäre also so:
Sie können zusätzlich
(HazardId, TaskId)
den Primärschlüssel deklarieren , wenn Sie diese Kombinationen aus einer anderen Tabelle referenzieren müssen. Um die Paare eindeutig zu halten, ist der Primärschlüssel jedoch nicht erforderlich. Es reicht aus, dass jede ID eindeutig ist.quelle
(HazardId, TaskId)
hat die Tupel(HazardId)
und(TaskId)
beide identifizieren eine Zeile dieser Tabelle eindeutig. Einer von ihnen sollte als Primärschlüssel ausgewählt werden.Um zusammenzufassen:
Wenn die Aufgaben- und Gefahrentabellen für etwas anderes verwendet werden (dh Aufgaben und / oder Gefahren sind mit anderen Daten verknüpft, und das Modell, das Sie uns gezeigt haben, wird vereinfacht, um nur die relevanten Felder anzuzeigen), würde ich sagen, dass Ihre Lösung korrekt ist.
Andernfalls benötigen Sie keine zwei Tabellen, wenn Aufgaben und Gefahren nur vorhanden sind, um miteinander gekoppelt zu werden. Sie können eine einzelne Tabelle für ihre Beziehung mit den folgenden Feldern erstellen:
quelle
TaskID
undHazardID
? Sie könnten 2 BIT Spalten haben,IsTask
,IsHazard
und eine Einschränkung , die nicht beide falsch sind. Dann ist dieHazard
Tabelle einfach eine Ansicht:CRAETE VIEW Hazard SELECT HazardID = ID, HazardDetails, ... FROM ThisTable WHERE IsHazard = 1;
bzw. Aufgabe.Ein anderer Ansatz, der noch nicht erwähnt worden zu sein scheint, besteht darin, dass Gefahren und Aufgaben denselben ID-Bereich verwenden. Wenn eine Gefahr eine Aufgabe hat, hat sie dieselbe ID. Wenn eine Aufgabe für eine Gefahr bestimmt ist, hat sie dieselbe ID.
Sie würden eine Sequenz anstelle von Identitätsspalten verwenden, um diese IDs zu füllen.
Abfragen für diese Art von Datenmodell würden (vollständige) äußere Verknüpfungen verwenden, um ihre Ergebnisse abzurufen.
Dieser Ansatz ist der Antwort von @ AndriyM sehr ähnlich, außer dass seine Antwort zulässt, dass die IDs unterschiedlich sind, und eine Tabelle zum Speichern dieser Beziehung.
Ich bin nicht sicher, ob Sie diesen Ansatz für ein Szenario mit zwei Tabellen verwenden möchten, aber er funktioniert gut, wenn die Anzahl der beteiligten Tabellen zunimmt.
quelle