2008-08-28 58 views
8

如何在transact sql中指定外鍵約束應該是1:1關係?是否聲明列UNIQUE足夠?以下是我現有的代碼。1:1外鍵約束

CREATE TABLE [dbo].MyTable(
    [MyTablekey] INT IDENTITY(1,1) NOT FOR REPLICATION NOT NULL, 
    [OtherTableKey] INT NOT NULL UNIQUE 
     CONSTRAINT [FK_MyTable_OtherTable] FOREIGN KEY REFERENCES [dbo].[OtherTable]([OtherTableKey]), 
    ... 
    CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
    (
     [MyTableKey] ASC 
    ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

回答

9

具有引用另一個表中的UNIQUE,NOT NULL列的UNIQUE和NOT NULL約束的外鍵列創建1:(0 | 1)關係,這可能是您想要的。

如果存在真正的1:1關係,則第一個表中的每個記錄都將在第二個表中具有相應的記錄,反之亦然。在這種情況下,你可能只想製作一張表(除非你需要一些奇怪的存儲優化)。

+2

..或需要超過SQL行長度限制。 Microsoft Dynamics CRM執行此操作可將內置列與用戶添加的列分開。 – BlackWasp 2009-02-23 22:13:46

4

您可以聲明該列是主鍵和外鍵。對於用於避免將可空列置於主表中的「擴展」表,這是一個很好的策略。

0

根據上面的代碼,如果您在表中具有每個主鍵,唯一約束就足夠了,唯一約束列也是唯一的。另外,這假設在[OtherTable]中,[OtherTableKey]列是該表的主鍵。

0

如果存在真正的1:1關係,則第一個表中的每個記錄都將在第二個表中具有相應的記錄,反之亦然。在這種情況下,你可能只想製作一張表(除非你需要一些奇怪的存儲優化)。

這是非常不正確的。讓我舉一個例子。您有一個與表SALES_OFFICE具有1:1關係的表CLIENT,例如,系統的邏輯如此表示。你真的將SALES_OFFICE的數據合併到CLIENT表中嗎?如果其他表需要將自我與SALES_OFFICE聯繫起來?那麼數據庫規範化最佳實踐和模式呢?

具有引用另一個表中的UNIQUE,NOT NULL列的UNIQUE和NOT NULL約束的外鍵列創建1:(0 | 1)關係,這可能是您想要的。

答案的第一部分是沒有第二部分的正確答案,除非第二個表中的數據實際上是屬於第一個表的一種信息,永遠不會被其他表使用。

1

@bosnic:

您必須有1臺客戶:因爲,例如,您的系統的邏輯是這樣說的帶表SALES_OFFICE 1的關係。

你的應用程序邏輯是什麼意思,你的數據模型說的是兩個不同的東西。與業務邏輯代碼一起執行這種關係沒有任何問題,但它在數據模型中沒有地位。

您是否真的將SALES_OFFICE的數據合併到CLIENT表中?

如果每個CLIENT都有一個唯一的SALES_OFFICE,並且每個SALES_OFFICE都有一個唯一的唯一客戶端 - 那麼是的,它們應該在同一個表中。我們只需要一個更好的名字。;)

如果其他表需要將自我與SALES_OFFICE聯繫起來嗎?

沒有理由。將您的其他表與CLIENT相關聯,因爲CLIENT具有唯一的SALES_OFFICE。

那麼數據庫規範化最佳實踐和模式呢?

正常化。公平地說,SALES_OFFICE和CLIENT顯然不是1:1的關係 - 它是1:N。希望您的SALES_OFFICE可以爲超過1個客戶提供服務,並且會在沒有任何客戶的情況下繼續存在(至少在一段時間內)。

更現實的例子是SALES_OFFICE和ZIP_CODE。 SALES_OFFICE必須正好有1個ZIP_CODE和2個SALES_OFFICE - 即使它們具有相同的ZIP_CODE - 不共享ZIP_CODE的實例(因此,更改1的ZIP_CODE不會影響另一個)。你不同意ZIP_CODE屬於SALES_OFFICE中的一列嗎?