﻿# 如何在 SQL Server 資料庫設計「一對一」表格關聯

我們在做資料庫設計時，通常都會需要設計表格之間的關聯，不過一般來說都是設定一對多的表格關聯，如果是多對多的表格關聯通常都會多設計一張表格來儲存兩個表格之間多對多的關聯關係。但是如果我們今天單純的只是想設計一些擴充欄位到另一個獨立的表格裡，這時我們在 SQL Server 裡還需要設計關聯嗎？還是在程式中自己知道就好不需要設計關聯呢？其實是需要的，只是很少人知道可以這樣設計而已！

在我的程式生崖中，鮮少有這種需要設計一對一表格關聯的情況，但是還是有遇到過幾次，但我發現負責資料庫設計的人甚至都還不知道原來 SQL Server 即便是一對一的表格還是能建立關聯的，建立關聯後不但是透過 **資料庫圖表** (**Database Diagram**) 可以清楚明瞭的知道表格之間的關係，甚至於在開發時期也能利用 ORM 技術來提高開發效率，本篇文章我還會以 Entity Framework 4 來說明在資料庫中建立一對一關聯的好處。

假設我們有一個名為 **ErrorLog** 的表格，因為專案的需求我們需要擴充此表格的欄位，但客戶不希望我們再更動現有資料表的結構 (Schema)，因此我們建立了另一個名為 **ErrorLogExt** 的表格，建立完成之後一樣也設定了一個 **主索引鍵** (Primary Key) 其欄位型態與 ErrorLog 的**主索引鍵**欄位型態一模一樣。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/0a8c43d727c342e4b97b-image_802.png)

這時若要建立一對一的表格關聯，可以在**資料庫圖表**中直接透過滑鼠拖曳的方式進行，不過拖曳的方向卻非常重要，今天我們雖然是一對一的關聯，但是還是有**主**、**副**之分，**主表格**為 **ErrorLog**，此表格是一定會有資料的，**副表格** (擴充資料存在的表格) 為 **ErrorLogExt**，此表格不一定會有資料。因此我們應該將滑鼠從 ErrorLog 表格的 ErrorLogID 欄位開始拖曳，拖曳到 ErrorLogExt 表格的 ErrorLogID 欄位之上，這時 Management Studio 就會自動幫我們把兩個表格之間的關聯建立起來，如下圖示：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/b6a9ee702d8925bf9697-image_803.png)

拖曳完成後 Management Studio 會出現一個確認畫面，這時你可以發現兩個表格之間的關係透過拖曳的方式都已經填好各欄位資料了，而且 **主表格** (Primary key table) 也已經選好了是 ErrorLog 資料表，按下 OK 之後確定：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/fbbe7fdd635e87f7f79f-SNAGHTML206e0af2.png)

然後我們可以展開 INSERT 及 UPDATE 規格 (INSERT And UPDATE Specification) 並在 刪除規格 (Delete Rule) 的地方選取 **重疊顯示** (Cascade)，設定重疊顯示的意思是說：「當主表格的那筆資料刪除的同時，另一個一對一關聯表格中相同的一筆資料也一併刪除」，這個設定不一定要這樣設計，還是要依據客戶的需求來決定是否一併刪除資料。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/24a964feabbc15c212bc-SNAGHTML20702ea8.png)

**備註**：Management Studio 中的翻譯很奇怪，Cascade 不應該翻譯為「重疊顯示」，這名詞讓初學者看到或英文不好的人看到，真的會一整個無法理解，若是翻譯成「串聯刪除」那就清楚多了。

當關聯建立完成後，你會發現兩個表格間的關聯圖示是**兩頭都有鑰匙的圖示**，這種圖示就代表者兩個表格之間設定了一對一的關聯關係。

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/be2335337648c16b459b-image_804.png)

不過這樣的設計過程跟我們設計「一對多關聯」時有什麼不一樣嗎？是的，完全一樣！差別僅在於你只要關聯兩個表格的時候，兩邊的欄位都選取**主索引鍵**欄位，SQL Server 就會自動識別為一對一關聯！在設計好關聯之後，接著我們來看 Entity Framework 在設計模型時會有什麼樣的結果。

我們在 Entity Framework 設計工具中使用「從資料庫更新模型」來載入新的表格定義：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/93e40d46f9a83340af8e-image_805.png)

加入後你會發現表格間的關聯也都會自動建立完成，而且是 1 對 0..1 的關係 (如下圖示)，這才是正確的一對一關係，如果你當初在資料庫中設定一對一關聯時不小心把主表格設定到 ErrorLogExt 時就會發現表格關係變成 0..1 對 1 的關係，那就不對了！

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/ca3a10fe98d539cdd513-image_806.png)

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/0740955e41582dea7161-image_807.png)

設定好關聯之後，日後我們在開發程式時也就非常方便了，如下範例程式：

![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/2ac9f4bcde6758fc8f5f-image_808.png)

透過 ORM 技術並設定好一對一關聯，我們就可以多利用俗稱的 **點表示法** ( **dot notation** ) 來開發程式，不但程式碼可以寫的更快，而且程式碼還更容易閱讀了，是不是一整個簡單直覺了許多呢！^\_\_^

**相關連結**

-   [資料表關聯性類型](http://msdn.microsoft.com/zh-tw/library/4s9x13w7.aspx)
-   [參考完整性概觀](http://msdn.microsoft.com/zh-tw/library/kcyehfs6.aspx)
-   [Defining a one-to-one relationship in SQL Server](http://stackoverflow.com/questions/1722741/defining-a-one-to-one-relationship-in-sql-server)
-   [SQL Server Database Design with a One To One Relationship](http://www.mssqltips.com/tip.asp?tip=2380)
