Jak w najbardziej naturalny sposób modelować relację zero-jedynka do zera jeden lub jeden w Sql Server?
Istnieje tabela „Zagrożenia”, która zawiera listę zagrożeń w witrynie. Istnieje tabela „Zadań” do pracy, którą należy wykonać na stronie. Niektóre zadania mają naprawić zagrożenie, żadne zadanie nie może poradzić sobie z wieloma zagrożeniami. Niektóre zagrożenia mają za zadanie je naprawić. Żadnemu zagrożeniu nie można przypisać dwóch zadań.
Poniżej jest najlepsze, o czym mogłem myśleć:
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
Czy zrobiłbyś to inaczej? Powodem, dla którego nie jestem zadowolony z tej konfiguracji jest to, że musi istnieć logika aplikacji, aby upewnić się, że zadania i zagrożenia wskazują na siebie nawzajem, a nie na inne zadania i zagrożenia, i że żadne zadanie / zagrożenie nie wskazuje na to samo zagrożenie / zadanie inne zadanie / zagrożenie wskazuje na.
Czy jest lepszy sposób?
źródło
null
.CREATE UNIQUE INDEX x ON dbo.Hazards(TaskID) WHERE TaskID IS NOT NULL;
Odpowiedzi:
Możesz pójść z własnym pomysłem na schemat asymetryczny, usuwając jeden z kluczy obcych z bieżącej konfiguracji, lub, aby zachować symetryczność, możesz usunąć oba klucze obce i wprowadzić tabelę połączeń z unikalnym ograniczeniem dla każdego odwołania .
Tak by wyglądało to tak:
Możesz dodatkowo zadeklarować,
(HazardId, TaskId)
że jesteś kluczem podstawowym, jeśli chcesz odwoływać się do tych kombinacji z innej tabeli. Jednak aby zachować unikalność par, klucz podstawowy jest niepotrzebny, wystarczy, aby każdy identyfikator był unikalny.źródło
(HazardId, TaskId)
ma krotki(HazardId)
i(TaskId)
oba jednoznacznie identyfikują rząd tej tabeli. Jeden z nich należy wybrać jako klucz podstawowy.Podsumowując:
Jeśli tabele zadań i zagrożeń są używane do czegoś innego (tj. Zadania i / lub zagrożenia mają inne powiązane dane, a model, który nam pokazałeś, jest uproszczony, aby pokazać tylko odpowiednie pola), powiedziałbym, że twoje rozwiązanie jest poprawne.
W przeciwnym razie, jeśli Zadania i Zagrożenia istnieją tylko w celu ich połączenia, nie potrzebujesz dwóch tabel; możesz utworzyć jedną tabelę dla ich relacji, z następującymi polami:
źródło
TaskID
iHazardID
? Można mieć 2 kolumny bit,IsTask
,IsHazard
i ograniczenie, które nie oba z nich są fałszywe. ZatemHazard
tabela jest po prostu odpowiednio widokiem:CRAETE VIEW Hazard SELECT HazardID = ID, HazardDetails, ... FROM ThisTable WHERE IsHazard = 1;
i zadaniem.Innym podejściem, które wydaje się jeszcze nie wspomniane, jest używanie zagrożeń i zadań w tej samej przestrzeni ID. Jeśli zagrożenie ma zadanie, będzie miało ten sam identyfikator. Jeśli zadanie dotyczy zagrożenia, będzie miało ten sam identyfikator.
Aby wypełnić te identyfikatory, należy użyć sekwencji zamiast kolumn tożsamości.
Kwerendy dotyczące tego typu modelu danych wykorzystywałyby (pełne) sprzężenia zewnętrzne do pobierania wyników.
To podejście jest bardzo podobne do odpowiedzi @ AndriyM, tyle że jego odpowiedź pozwala na różne identyfikatory i tabelę do przechowywania tej relacji.
Nie jestem pewien, czy chcesz zastosować to podejście do scenariusza z dwiema tabelami, ale działa ono dobrze, gdy wzrasta liczba zaangażowanych tabel.
źródło