Belirli bir tablonun birkaç farklı üst tablolardan birine FK yapabileceği oldukça sık veritabanında bir durumla karşılaşıyorum. Sorun için iki çözüm gördüm, ama ikisi de kişisel olarak tatmin edici değil. Orada başka hangi desenleri gördüğünüzü merak ediyorum. Bunu yapmanın daha iyi bir yolu var mı?
Düzenlenmiş Bir Örnek
Diyelim ki sistemim var Alerts
. Çeşitli nesneler için uyarılar alınabilir - Müşteriler, Haberler ve Ürünler. Belirli bir uyarı yalnızca bir öğe için olabilir. Hangi nedenle olursa olsun, Müşteriler, Makaleler ve Ürünler hızlı hareket eder (veya yerelleştirilir), bu nedenle gerekli metin / veriler bir Uyarı oluşturulduktan sonra Uyarılara alınamaz. Bu kurulum göz önüne alındığında iki çözüm gördüm.
Not: Aşağıda DDL SQL Server içindir, ancak sorum herhangi bir DBMS için geçerli olmalıdır.
Çözüm 1 - Birden Çok Sıfırlanabilir FKey
Bu çözümde, çok sayıda tablodan birine bağlanan tabloda birden fazla FK Sütunu vardır (kısaca, aşağıdaki DDL, FK oluşturma işlemini göstermez). İYİ - Bu çözümde yabancı anahtarları olması güzel. FK'lerin boş olması, doğru veri eklemek için bu kullanışlı ve nispeten kolay hale getirir. KÖTÜ Sorgulama harika değildir, çünkü ilişkili verileri almak için N LEFT JOINS veya N UNION deyimi gerektirir . SQL Server'da, özellikle LEFT JOINS dizinlenmiş bir görünüm oluşturmayı engeller.
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)
)
Çözüm 2 - Her Ebeveyn Tablosunda
bir FK Bu çözümde her 'üst' tablonun Uyarı tablosunda bir FK vardır. Bir ebeveynle ilişkili uyarıları almayı kolaylaştırır. Aşağı tarafta, Alert'ten kimin referans aldığı için gerçek bir zincir yoktur. Ayrıca, veri modeli, bir uyarının bir Ürün, Haberler veya Müşteri ile ilişkili olmadığı, artık Uyarılara izin verir. Yine, ilişkiyi anlamak için birden fazla SOL BİRLEŞME.
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)
)
Bu bir ilişki veri tabanındaki hayat mı? Daha tatmin edici bulduğunuz alternatif çözümler var mı?
Alertable
. Bu bir anlam ifade ediyor mu?