2010-06-13 91 views
2

我有一個關於那個我設計並確保它是一個標準化的數據庫中快速的問題...簡單的數據庫正常化問題

我有一個客戶表,與客戶ID的主鍵。它有一個StatusCode列,其中有一個反映客戶帳戶狀態的代碼,即。 1 =打開,2 =關閉,3 =暫停等...

現在我想在客戶表中有另一個字段標記帳戶是否被允許暫停或不...某些客戶將如果他們打破那裏的交易條款......別人不會自動掛起......所以相關表中的字段會像這樣:

客戶(客戶編號(PK):的StatusCode:IsSuspensionAllowed)

現在,這兩個領域都依賴因爲您無法確定特定客戶的狀態或是否允許暫停,除非您知道特定客戶,當然,當IsSuspensionAllowed字段設置爲YES時,客戶永遠不應該有StatusCode爲3(暫停)。

從上表設計看來,除非檢查限制添加到我的表中,否則可能發生這種情況。我看不出如何將另一個表添加到關係設計中來強制執行此操作,因爲只有在IsSuspensionAllowed設置爲YES且StatusCode設置爲3(兩者相互依賴時)的情況下。

因此,在我漫長的解釋後,我的問題是:這是一個規範化問題,我沒有看到一個關係設計,將強制執行此操作......或者它實際上只是一個業務規則,應該強制執行檢查約束並且表格實際上仍然正常化。

乾杯,

史蒂夫

回答

0

是的,它是可能的。您可以使用檢查約束和Case語句執行此操作:

Create Table Customer (
     CustomerId <datatype> not null Primary Key 
     , StatusCode int not null 
     , IsSuspensionAllowed int not null Default(1) 
     , Constraint CK_Customer_IsSuspensionAllowed 
        Check (IsSuspensionAllowed In(0,1)) 
     , Constraint CK_Customer_StatusCodeRange 
        Check (StatusCode Between 0 And ??) 
     , Constraint CK_Customer_StausCodeValid 
        Check (Case 
       When StatusCode = 3 And IsSuspensionAllowed = 1 Then 0 
                   Else 1 
                   End = 1) 
     , .... 
     ) 

您沒有提到PK的數據類型,因此我只是插入了佔位符。如果您使用的是SQL Server,那麼可以使用一個位列來代替int和我上面提到的檢查約束(bit不是ANSI規範的一部分)。

這是一個很好的例子,例如狀態代碼的替代鍵並不總能很好地工作。字符串值代表狀態碼會更好,在這種情況下,Case語句將顯示爲When StatusCode = 'Suspended' And IsSuspendedAllowed = 0...

從規範化的角度來看,我沒有看到任何錯誤。是否允許暫停是特定於客戶的屬性,而不是其他屬性。你說的檢查約束,屬性值的某些狀態不能存在,這很好。

順便說一句,當IsSuspensionAllowed = 0時不允許說「Suspended」的狀態是不允許的?使用你的數據,不應該是不允許的狀態是StatusCode = 3 and IsSuspensionAllowed = 0

+0

謝謝, 我正在規範化和「完整的鑰匙,但沒有什麼,但關鍵」的事情正在給一些懷疑。我覺得Status和IsSuspended之間可能存在傳遞依賴關係。正如你所提到的,儘管每個屬性都是特定於客戶的。 我承認我喜歡在大多數情況下使用代理鍵進行標準化。我通常只會遇到已經開發的標準,比如貨幣,或者代表多對多關係的表格。我對你的評論是關於如何提高板載可讀性,並且會認爲它是不變的代碼。 乾杯 – Steven 2010-06-13 05:52:17