Sql-Server

數據庫設計 - 兩個或多個聯結表之間的關係

  • July 22, 2022

我是一名初級開發人員,我不知道如何實現下一個關係。

注意:此處描述的所有實體都是虛構的,但在實際生產數據庫中具有等價物。性能無關緊要(可以使用太多的聯結表),但優化架構會很好。

附加資訊:使用 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 NULLFOREIGN KEY保持完整性。

Job_Address表格視為您的“實際工作”列表 - 在某個地址發生的某些工作的實例。但是,由於它們是多對多的關係,您需要分別將作業名稱和地址分解到JobAddress表中 - 您在原始模型中已經這樣做了。我認為這裡的解決方案是人們與“實際工作”的實例相關聯,而不是直接與工作名稱和地址的主列表相關聯。

程式碼

下面是一些 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

以下是查詢結果:

在此處輸入圖像描述

引用自:https://dba.stackexchange.com/questions/314709