空值

2012-06-15 28 views
2

假設我有一個表1,有三列:ID(主鍵,標識),A和B空值

現在,假設我有3種方法,假設他們兩個沒有共同點,列〜明智:

方法1:C,d,E

方法2:F,G,H,I

方法3:J-

我可以使一個表: ID,A , B,C,D,E,F,G,H,I,J,M

其中M是方法(或方法ID)的名稱。

但是,如果使用方法3的90%時間,則會有很多空值。
這是一個問題嗎?如果是這樣,是否有更好的方法來設置呢?

如果我讓每個方法都有自己的表格實體,我如何確保每個ID都有一個匹配它的方法?

如果我把它作爲一個表格,我如何確保只有C,D,E被填充並且F到J是NULL,如果M是1?


OK,似乎已經有很多人難以抽象思維,所以我將創建應用上述隨機具體的例子:

假設我的人進行鍛鍊記錄。
每條記錄​​始終有一個ID(用於唯一標識該事件),一個TIME_STARTED和TIME_ENDED。

但是,根據他們做了哪些練習,會有不同的屬性需要。假設只有三個練習:

橢圓:傾斜面,平,速度快

仰臥起坐:User_Weight,代表,延遲,Extra_Weight

硬拉:Weight_Lifted

對於每個ID只能有一個「方法」。應用這個,參見上面的問題。

+3

你是什麼意思的方法?如果你的表只有ID,A,B,c,d,e,f,g,h,i,j,m從哪裏來? – YavgenyP

+3

你可能會在這裏問錯誤的問題。從「我需要存儲X數據,最佳模式是什麼」開始,可能會更好一些。由於我們沒有上下文,不知道ABCDEFGHIJM是什麼,因此它很難提供幫助,但是這聽起來像是在走向一個非常錯誤的方向。 –

+0

假設我記錄了測試運行,ID,A和B始終是每次運行的一部分。但是,如果運行是使用方法1完成的,則需要將值存儲在C,D和E列中。與方法2運行需要列F,G,H,I等相比,這可能是不同的數據類型。 – user17753

回答

3

聽起來你在這裏有一個supertype/subtype的情況。在這種情況下,Table1保存超類型,並且您希望創建一個不同的表來保存每個子類型。這些子類型表上的PK也是超類型表的FK。所以你會有這樣的事情:

Supertype_table 
| ID(PK) | A | B | 

Subtype1_table 
| ID(PK&FK) | C | D | E | 

Subtype2_table 
| ID(PK&FK) | F | G | H | I | 

Subtype3_table 
| ID(PK&FK) | J | 

這種模式的要點是要確保你沒有一堆行大多是空值。對於每種方法,您都必須編寫一個單獨的查詢來插入/更新適當的表格。使用SQL Server,你可以結合了所有這些表和抽象了任何加入了一個觀點:

CREATE VIEW MyView 
SELECT Super.ID, Super.A, Super.B, 
Sub1.C, Sub1.D, Sub1.E, 
Sub2.F, Sub2.G, Sub2.H, Sub2.I, 
Sub3.J 
FROM Supertype_table as Super 
LEFT OUTER JOIN Subtype1_table as Sub1 on Super.ID = Sub1.ID 
LEFT OUTER JOIN Subtype2_table as Sub2 on Super.ID = Sub2.ID 
LEFT OUTER JOIN Subtype3_table as Sub3 on Super.ID = Sub3.ID 

,那麼你可以只寫類似:

SELECT ID, A, B, J 
FROM MyView 
WHERE J is not null 

編輯:對於OP的評論

爲了確保每個ID是唯一一個表,你需要在超表某種標識符。所以,如果你有一個名爲TYPEID列,您將創建功能:

CREATE FUNCTION [dbo].[SubtypeofSuperID](@ID int) 
RETURNS int 
AS 
BEGIN 
    DECLARE @TypeID int; 

    SELECT @TypeID = TypeID 
    FROM Supertype_table 
    WHERE ID = @ID 

    RETURN @TypeID 
END 

然後,利用這一點,你可以在每個亞型表的創建檢查:

ALTER TABLE Subtype1_table CONSTRAINT [CK_CorrectSubtype1] 
CHECK ([dbo].[SubtypeofSuperID]([ID]) = 1) 
ALTER TABLE Subtype2_table CONSTRAINT [CK_CorrectSubtype2] 
CHECK ([dbo].[SubtypeofSuperID]([ID]) = 2) 
ALTER TABLE Subtype3_table CONSTRAINT [CK_CorrectSubtype3] 
CHECK ([dbo].[SubtypeofSuperID]([ID]) = 3) 
+0

我最初的想法是這樣的,但是我有一個問題。有可能有多個子類型表都指向相同的超類型行。如何確保只有一個Supertype行適用於一個且僅有一個子類型表(以及該表內的行)。 – user17753

+0

例如如果我想要不相交的子類型,我想使用Supertype中的一列作爲子類型鑑別器。基於邏輯檢查在我的最後插入實施?或者DB可以設置爲自動禁止這種插入? – user17753

+1

您必須以某種方式進行明確檢查。我使用函數+檢查方法,它適用於我。我還會確保在客戶端代碼中執行檢查,以便用戶在嘗試執行某些他們不應該執行的操作時收到錯誤消息。對我而言,數據庫檢查是最後一道防線。 – Jason

1

幾種方法...

首先,賈森的回答擊中他們中的一個 - 突破你設計出到多個表 - 這可以爲大部分事情相當不錯的辦法。 (亦稱更加「標準化」的方法)

替代...

1)你可以有名稱 - 值對的最後一個字段的字符串。例如:

ID Method DateTimeStart DateTimeEnd ValueString 
1 1  2012-01-01... 2012-01-01... C:value,D:value,E:value 
2 2  2012-01-01... 2012-01-01... F:value,G:value,H:value,I:value 

所以這可能是在那裏你不能提前值類型計劃的情況下派上用場。例如,也許你需要能夠立即決定開始記錄方法1的'W'值,並且做一個結構模式是不可行的,就像你在一個更規範的設計中必須做的那樣。

這是我們的E-標誌表單開發人員使用的常用方法。您可以想象一個網絡表單,例如某人將填寫並通過電子途徑進行審批的「部門請假」。然後,一位客戶希望他們建立一個「採購訂單」的網頁表單,該表單必須記錄不同的字段值。而不是爲此創建全新的表(或列添加到現有表等),他們使用的名稱 - 值對模型來存儲所有形式的數據,無論哪種形式是,在同一個表。

2)您可以使用表觸發器來強制實現完整性,如果你不信任運行在您的單一大表插入的人/過程。例如,更新前觸發器可以檢查方法編號,然後通過取消任何不適當的數據值來修改個人或進程試圖插入的數據。

FWIW