Często spotykam się z sytuacją w bazie danych, w której dana tabela może przejść do jednej z wielu różnych tabel nadrzędnych. Widziałem dwa rozwiązania problemu, ale żadne z nich osobiście nie jest satysfakcjonujące. Jestem ciekawy, jakie inne wzory tam widziałeś? Czy jest na to lepszy sposób?
Przemyślany przykład
Załóżmy, że mój system ma Alerts
. Alerty mogą być odbierane dla różnych obiektów - klientów, wiadomości i produktów. Dany alert może dotyczyć tylko jednego elementu. Z jakiegokolwiek powodu klienci, artykuły i produkty szybko się przemieszczają (lub lokalizują), dlatego nie można pobrać niezbędnych tekstów / danych do alertów po utworzeniu alertu. Biorąc pod uwagę tę konfigurację, widziałem dwa rozwiązania.
Uwaga: poniżej DDL dotyczy SQL Server, ale moje pytanie powinno dotyczyć dowolnego DBMS.
Rozwiązanie 1 - Wiele kluczy zerowalnych FKeys
W tym rozwiązaniu tabela, która prowadzi do jednej z wielu tabel, ma wiele kolumn FK (ze względu na zwięzłość poniższy DDL nie pokazuje tworzenia FK). DOBRY - W tym rozwiązaniu fajnie jest mieć klucze obce. Brak optyki FK sprawia, że jest to wygodne i stosunkowo łatwe do dodawania dokładnych danych. ZŁE Zapytanie nie jest świetne, ponieważ wymaga N LEWEJ ŁĄCZENIA lub N UNII instrukcji, aby uzyskać powiązane dane. W SQL Server konkretnie LEWE POŁĄCZENIA wykluczają tworzenie widoku indeksowanego.
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)
)
Rozwiązanie 2 - Jeden FK w każdej tabeli nadrzędnej
W tym rozwiązaniu każda tabela „nadrzędna” ma FK do tabeli alertów. Ułatwia pobieranie alertów powiązanych z rodzicem. Z drugiej strony nie ma prawdziwego łańcucha od alertu do tego, kto się do niego odwołuje. Ponadto model danych pozwala na osierocone ostrzeżenia - w przypadku gdy alert nie jest powiązany z produktem, wiadomością lub klientem. Ponownie wiele LEWYCH DOŁĄCZ, aby dowiedzieć się o powiązaniu.
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)
)
Czy to tylko życie w bazie danych relacji? Czy istnieją alternatywne rozwiązania, które uważasz za bardziej satysfakcjonujące?
źródło
Alertable
. Czy to ma jakiś sens?Odpowiedzi:
Rozumiem, że drugie rozwiązanie nie ma zastosowania, ponieważ nie oferuje relacji jeden (obiekt) z wieloma (alert).
Trzymasz się tylko dwóch rozwiązań ze względu na ścisłą zgodność 3NF.
Zaprojektowałbym mniejszy schemat sprzęgania:
Lub, jeśli relacja uczciwości będzie obowiązkowa, mogę zaprojektować:
Tak czy siak...
Trzy prawidłowe rozwiązania plus inne do rozważenia dla wielu relacji (obiektów) z jednym (alertem) ...
Przedstawione, jaka jest moralność?
Różnią się subtelnie i mają taką samą wagę według kryteriów:
Więc wybierz ten program dla ciebie.
źródło
Użyłem utrzymywanych przez wyzwalacze tabel łączenia. rozwiązanie działa całkiem dobrze w ostateczności, jeśli refaktoryzacja bazy danych nie jest możliwa lub pożądana. Chodzi o to, że masz tabelę, która jest po to, aby poradzić sobie z problemami RI, a wszystkie DRI są temu przeciwne.
źródło