2013-10-24 44 views
7

我已經在不同的項目最近碰上這種情況下多次。這裏有一個圖的四個表,標有字母:四臺關係設計

 A 
    1/\ 1 
/ \ 
*/ \ * 
B  C 
1 \ /1 
    \ /
    * \/* 
    D 

在這種情況下,有可能將數據變得不一致如果從按鍵到BACA不匹配的給出D

對於一個特定的(由)例如,假設ACompanyBEmployeeCProject,和DWorkItem。在這種情況下,沒有任何東西可以阻止創建的工作項目聲稱被分配給甚至沒有爲擁有該項目的公司工作的人員。

我主要只是好奇,有沒有一個設計解決這個問題?我知道在真正的應用程序中,您可以使用觸發器或其他安全措施。我還沒有找到改變表格的方法,使這種不一致是不可能的。有沒有辦法?

注意,只是切斷了連接中的一個,就像從CA不起作用,因爲如果該C不存在D的,你就沒有追查連接回A的方式。

+0

好問題。我一直採取保護措施來防止應用程序層中出現這種情況。看看別人要說什麼會很有趣。 –

+0

我用來在業務規則中執行這種限制,而不是觸發器。 –

+0

重新定義您的實體:employee - >> person(記住:ex-emplyee曾經是員工一次)可能需要添加時間軸(以及其他一些額外維度;查找隱藏維度)。 – wildplasser

回答

7

使用複合鍵(即,包括一個鍵多個字段),用於在下游的表。然後,在d,你可以只使用一個場舉行的關鍵:

[編輯:固定在D的第二FK愚蠢複製&粘貼錯誤]

CREATE TABLE A (
    A_ID INTEGER PRIMARY KEY 
    -- Any other fields you want... 
); 

CREATE TABLE B (
    A_ID INTEGER REFERENCES A.A_ID, 
    B_ID INTEGER, 
    -- Any other fields you want... 
    PRIMARY KEY (A_ID, B_ID) 
); 

CREATE TABLE C (
    A_ID INTEGER REFERENCES A.A_ID, 
    C_ID INTEGER, 
    -- Any other fields you want... 
    PRIMARY KEY (A_ID, C_ID) 
); 

CREATE TABLE D (
    A_ID INTEGER, -- This field forms part of the FK for BOTH B and C 
    B_ID INTEGER, 
    C_ID INTEGER, 
    D_ID INTEGER, 
    -- Any other fields you want... 
    PRIMARY KEY (A_ID, B_ID, C_ID, D_ID), 
    FOREIGN KEY (A_ID, B_ID) REFERENCES B (A_ID, B_ID), 
    FOREIGN KEY (A_ID, C_ID) REFERENCES C (A_ID, C_ID) 
); 

我沒有測試過上述SQL,但你希望得到這個想法。請注意,D不需要第三個FK約束返回給A,因爲這已經被其他FK隱含(實際上它們分別由它們各自隱含)。

引用完整性檢查總是比觸發器更好 - 至少在PostgreSQL中是這樣的,我懷疑所有RDBMS都是如此。

+0

我相信這是唯一的方式,但是是一個發展地獄(其他實體可能需要更長的鑰匙)。性能可能也很糟糕。 –

+1

@LuisMartinez:我期望使用單個整數(或者可能是GUID)PK更快,但是我還沒有在PostgreSQL上以這種方式組織表的性能問題,其中一些表有幾百萬行。實際上,我發現它使調試變得更加容易 - 在使用某個從屬表的記錄時,您的PK會立即告訴您很多信息,而不僅僅是一個不透明的令牌。其次,您通常可以按這些FK字段排序或分組,而不需要加入父表。 –