Yabancı anahtarlar için null alanlarını kullandığınızdan, aslında sizin öngördüğünüz şekilde doğru çalışan bir sistem oluşturabilirsiniz. Hesaplar tablosuna satır eklemek için, Kayıtlar tablosunda boş bir PrimaryContactID olan Hesaplara eklenmesine izin vermediğiniz sürece bir satırınız olması gerekir. Zaten bir Hesap satırına sahip olmadan bir irtibat satırı oluşturmak için, Kişiler tablosundaki Hesap Kimliği sütununun geçersiz olmasına izin vermelisiniz. Bu, Hesapların hiçbir kişilere sahip olmamasını ve Kişilerin hiç hesap sahibi olmamasına izin verir. Belki de bu arzu edilir, belki de değildir.
Bunu söyledikten sonra, kişisel tercihim şu kurulumu yapmak olacaktır:
CREATE TABLE dbo.Accounts
(
AccountID INT NOT NULL
CONSTRAINT PK_Accounts
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, AccountName VARCHAR(255)
);
CREATE TABLE dbo.Contacts
(
ContactID INT NOT NULL
CONSTRAINT PK_Contacts
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, ContactName VARCHAR(255)
);
CREATE TABLE dbo.AccountsContactsXRef
(
AccountsContactsXRefID INT NOT NULL
CONSTRAINT PK_AccountsContactsXRef
PRIMARY KEY CLUSTERED
IDENTITY(1,1)
, AccountID INT NOT NULL
CONSTRAINT FK_AccountsContactsXRef_AccountID
FOREIGN KEY REFERENCES dbo.Accounts(AccountID)
, ContactID INT NOT NULL
CONSTRAINT FK_AccountsContactsXRef_ContactID
FOREIGN KEY REFERENCES dbo.Contacts(ContactID)
, IsPrimary BIT NOT NULL
CONSTRAINT DF_AccountsContactsXRef
DEFAULT ((0))
, CONSTRAINT UQ_AccountsContactsXRef_AccountIDContactID
UNIQUE (AccountID, ContactID)
);
CREATE UNIQUE INDEX IX_AccountsContactsXRef_Primary
ON dbo.AccountsContactsXRef(AccountID, IsPrimary)
WHERE IsPrimary = 1;
Bu yetenek sağlar:
- Pieter'in cevabında önerdiği şekilde çapraz referans tablosu üzerinden irtibatlar ve hesaplar arasındaki ilişkileri açıkça belirtin
- Referans bütünlüğünü sağlam, dairesel olmayan bir şekilde koruyun.
- İndeks aracılığıyla birincil düzeyde irtibatlandırılabilecek birincil irtibatlar listesi sağlayın
IX_AccountsContactsXRef_Primary
. Bu dizin bir filtre içerir, bu nedenle yalnızca onları destekleyen platformlarda çalışır. Bu dizin UNIQUE
seçeneği ile belirtildiğinden, her hesap için yalnızca tek bir birincil bağlantı olabilir.
Örneğin, tüm kişilerin listesini görüntülemek istiyorsanız, "birincil" durumunu belirten ve her bir hesap için listenin başında birincil kişileri gösteren bir sütunu olan bir sütun görüntülemek isterseniz, şunları yapabilirsiniz:
SELECT A.AccountName
, C.ContactName
, XR.IsPrimary
FROM dbo.Accounts A
INNER JOIN dbo.AccountsContactsXRef XR ON A.AccountID = XR.AccountID
INNER JOIN dbo.Contacts C ON XR.ContactID = C.ContactID
ORDER BY A.AccountName
, XR.IsPrimary DESC
, C.ContactName;
Filtrelenmiş dizin, hesap başına tek bir birincil temastan daha fazlasını eklemeyi önlerken, aynı anda birincil temasların bir listesini hızlı bir şekilde geri gönderme yöntemi sağlar. IsActive
Hesap başına kişi geçmişini korumak için benzersiz olmayan filtrelenmiş bir dizine sahip başka bir sütunu kolayca düşünebilirsiniz , hatta bu kişi artık hesapla ilişkilendirilmezse:
ALTER TABLE dbo.AccountsContactsXRef
ADD IsActive BIT NOT NULL
CONSTRAINT DF_AccountsContactsXRef_IsActive
DEFAULT ((1));
CREATE INDEX IX_AccountsContactsXRef_IsActive
ON dbo.AccountsContactsXRef(IsActive)
WHERE IsActive = 1;