數據庫設計 - 兩個或多個聯結表之間的關係
我是一名初級開發人員,我不知道如何實現下一個關係。
注意:此處描述的所有實體都是虛構的,但在實際生產數據庫中具有等價物。性能無關緊要(可以使用太多的聯結表),但優化架構會很好。
附加資訊:使用 Entity Framework Code First 在 SQL Server 上生成表。
語境
我有一個名為 People 的實體,另一個名為 HomeAddress,最後一個名為 Job。它們之間具有多對多的關係,例如 People <-> Job 和 Job <-> HomeAddress。(連接表的名稱中有一個下劃線)。
這也需要與其他表一起複製,包括一個用於電話號碼的表。
問題
鑑於這種情況,我如何連結人員和地址。問題是一些工作有地址,而另一些則沒有。我需要 People 和 Job 之間的關係,並在可用時指定地址(所有視覺檢查都將在客戶端完成)。
- 範例 1:Alice 有一個沒有地址的 Job1。數據被插入數據庫而不指定地址。
- 範例 2:Bob 有一個包含 2 個地址的 Job2。Bob 從列表中選擇 1 個地址。將數據插入數據庫,為 Job2 指定 1 個地址。
- 範例 3:Charlie 有一個包含 4 個地址的 Job3。查理選擇了所有 4 個。插入數據,指定 Job3 的所有 4 個地址。
我不知道如何在給定此架構的情況下儲存這些資訊,因為 Address 應該依賴於 Job 並且如果 Job 從 People 中刪除,Address 也應該如此。
嘗試過的解決方案
- 我試圖在 Job_People 和 HomeAddress 之間建立一個連結,但由於 Job 可以擁有該資訊,這似乎是多餘的。
- 我能想到的另一個解決方案是在 People 和 HomeAddress 之間還有一個額外的連接表,就像 People <-> HomeAddress。我只是不知道這是否是正確的決定。
同樣,所有實體名稱都無關緊要,但它們的關係正是我要尋找的。
任何幫助表示讚賞。
這個模型對你有用嗎?
如果我理解正確,人們不會直接與工作或地址相關聯。相反,人們與預先建立的工作和地址*配對相關聯。*一個轉折是地址是可選的,但沒關係;我們仍然可以在 SQL Server 中使用關係約束(例如 )對此進行建模
NOT NULL
以FOREIGN KEY
保持完整性。將
Job_Address
表格視為您的“實際工作”列表 - 在某個地址發生的某些工作的實例。但是,由於它們是多對多的關係,您需要分別將作業名稱和地址分解到Job
和Address
表中 - 您在原始模型中已經這樣做了。我認為這裡的解決方案是人們與“實際工作”的實例相關聯,而不是直接與工作名稱和地址的主列表相關聯。程式碼
下面是一些 T-SQL 語句,它們根據上圖建構表,用原始文章中的三個範例填充它們,並顯示結果。
創建表
請注意,在我們的
Job_Address
表格中,工作 (JobID
) 是必需的 (NOT NULL
),但地址 (AddressID
) 不是 (NULL
)。-- Master lists of Jobs, Addresses, and Persons CREATE TABLE Job ( ID INT PRIMARY KEY ,Name VARCHAR(64) ); CREATE TABLE Address ( ID INT PRIMARY KEY ,Name VARCHAR(64) ); CREATE TABLE Person ( ID INT PRIMARY KEY ,Name VARCHAR(64) ); GO -- Associations CREATE TABLE Job_Address ( ID INT PRIMARY KEY ,JobID INT NOT NULL FOREIGN KEY REFERENCES Job (ID) ,AddressID INT NULL FOREIGN KEY REFERENCES Address (ID) ,Comments VARCHAR(64) ,CONSTRAINT Job_AddressU1 UNIQUE ( JobID ,AddressID ) ); CREATE TABLE Person_Job_Address ( PersonID INT FOREIGN KEY REFERENCES Person (ID) ,Job_AddressID INT FOREIGN KEY REFERENCES Job_Address (ID) ,CONSTRAINT Person_Job_Address_PK PRIMARY KEY( PersonID ,Job_AddressID ) ) GO
插入範例數據
三個“主列表”包含您在三個範例中描述的所有工作、地址和人員。“關聯”實現您的範例。
-- Master lists of Jobs, Addresses, and Persons INSERT INTO Job VALUES (1, 'Job 1'); INSERT INTO Job VALUES (2, 'Job 2'); INSERT INTO Job VALUES (3, 'Job 3'); INSERT INTO Address VALUES (1, 'Address 1'); INSERT INTO Address VALUES (2, 'Address 2'); INSERT INTO Address VALUES (3, 'Address 3'); INSERT INTO Address VALUES (4, 'Address 4'); INSERT INTO Person VALUES (1, 'Alice'); INSERT INTO Person VALUES (2, 'Bob'); INSERT INTO Person VALUES (3, 'Charlie'); -- Job and Address associations INSERT INTO Job_Address VALUES (1, 1, NULL, 'Alice example: One job with no address'); INSERT INTO Job_Address VALUES (2, 2, 1, 'Bob example: The job he chose'); INSERT INTO Job_Address VALUES (3, 2, 2, 'Bob example: The job he did not choose'); INSERT INTO Job_Address VALUES (4, 3, 1, 'Charlie example: Job one of four'); INSERT INTO Job_Address VALUES (5, 3, 2, 'Charlie example: Job two of four'); INSERT INTO Job_Address VALUES (6, 3, 3, 'Charlie example: Job three of four'); INSERT INTO Job_Address VALUES (7, 3, 4, 'Charlie example: Job four of four'); -- Person associations with Job/Address pairings INSERT INTO Person_Job_Address VALUES (1, 1) -- Alice; INSERT INTO Person_Job_Address VALUES (2, 2) -- Bob; INSERT INTO Person_Job_Address VALUES (3, 4) -- Charlie; INSERT INTO Person_Job_Address VALUES (3, 5) -- Charlie; INSERT INTO Person_Job_Address VALUES (3, 6) -- Charlie; INSERT INTO Person_Job_Address VALUES (3, 7) -- Charlie; GO
結果
最後,這是一個顯示各種關聯結果的聲明。請注意,Alice 的範例沒有地址,並且 Bob 僅與兩個工作/地址對之一相關聯。Charlie 與所有四個作業/地址實例相關聯。
SELECT Job_Address.ID ,Job.Name JobName ,Address.Name AddressName ,Person.Name PersonName ,Job_Address.Comments FROM Job_Address LEFT JOIN Job ON Job_Address.JobID = Job.ID LEFT JOIN Address ON Job_Address.AddressID = Address.ID LEFT JOIN Person_Job_Address ON Job_Address.ID = Person_Job_Address.Job_AddressID LEFT JOIN Person ON Person_Job_Address.PersonID = Person.ID ; GO
以下是查詢結果: