2013-02-17 78 views
3

我有一張名爲assets的表,其中資產可以屬於用戶,團隊或部門,並且可能屬於各自的多個部分。我的問題是,資產是高度可變的,並且可以具有與它們相關的屬性,每個屬性都不相同。什麼是在關係數據庫中存儲'元數據'的正確方法?

ex。這些可能是資產:

1.) 
type:workbench 
cost:200 
vendor:Acme Co. 
color:black 
2.) 
type:microscope 
serial_no:BH-00102 
purchase_date:1337800923 
cost:2040 

這可能會持續數百到數千種不同類型的資產。

我該如何以標準化的方式存儲這種類型的數據,而且每次添加新的資產類型時都不會改變我的表格,而不會改變我的表格?一些領域也是跨越所有資產的現在,例如成本。

到目前爲止,我想我應該有:

assets 
id,cost,purchase_date,asset_type_id 

asset_types 
id,name 

division_assets 
division_id,asset_id 

user_assets 
user_id,asset_id 

,但我不知道在哪裏把那個變化

+0

是一個屬性可以與數量的資產? – 2013-02-17 07:40:31

+0

有些屬性適用於所有資產,但其他屬性不適用於單個資產類型。 – Ethan 2013-02-17 07:41:16

+1

你打算去搜索那些變量屬性嗎?另外,請閱讀[EAV](http://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model) – 2013-02-17 07:53:55

回答

2

我建議這個數據:

assets (

    id 
    asset_type_id 
    vendor_id 
    cost 
    purchase_date 

) 

asset_poperties (

    id 
    asset_id 
    asset_property_type_id 
    value 

) 

asset_property_types (

    id 
    property_type 

) 

asset_types (

    id 
    asset_type 

) 

vendors (

    id 
    vendor 

) 
+0

這不允許使用變量字段 – Ethan 2013-02-17 07:44:58

+0

因此,更改的屬性存放在資產表中,常見的屬性存儲在單獨的表(asset_types,供應商...)中,並通過外鍵鏈接到資產表。 – 2013-02-17 07:46:33

+0

但用戶可以添加將附加不同數據的資產類型,但我不希望用戶能夠更改數據庫的結構。 – Ethan 2013-02-17 07:47:36

1

你可以爲asset_metadata添加另一個表格

asset_metadata 
asset_metadata_id,asset_id,metadata_name,metadata_value 

如果要規範和分類的元數據,將它規範化爲這樣:

asset_metadata 
asset_metadata_id,asset_id,metadata_name_id,metadata_value 

metadata_name 
metadata_name_id,metadata_name_text 
0

我建議把公共屬性像常規列成本。然後再添加一列,在其中添加所有其他可變資產屬性的序列化集合。

CREATE TABLE assets (
    asset_id INT AUTO_INCREMENT PRIMARY KEY, 
    cost NUMERIC(9,2), 
    purchase_date DATE, 
    variables TEXT 
); 

您可以將集合序列化爲JSON或XML或任何您想要的。使用您的應用程序代碼最容易處理的內容。

INSERT INTO assets VALUES (123, 49.95, CURDATE(), 'color: black; vendor: Acme Co.'); 

優點是您可以隨時向文本blob添加新的屬性。缺點是你不能讀取或寫入一個單獨的屬性,你必須將整個集合視爲一個整體。

但是,您可以對各個屬性進行索引以使其可供搜索。您需要創建一個新的表,你想搜索的每個屬性(但,這可能是所有屬性的一小部分):

CREATE TABLE asset_color (
    asset_id INT NOT NULL, 
    color VARCHAR(10), 
    PRIMARY KEY (asset_id, color), 
    KEY(color) 
); 

並不是每一個資產被記錄在這個表中,只有擁有這些資產顏色。

然後,你可以做的是有顏色屬性的所有資產索引搜索:

SELECT assets.* 
FROM assets INNER JOIN asset_color USING (asset_id); 

你也可以做一個索引搜索僅限於具有顏色屬性的資產,並且顏色爲黑色:

SELECT assets.* 
FROM assets INNER JOIN asset_color USING (asset_id) 
WHERE color = 'black'; 

真的沒有辦法設計一個規範化的數據庫,它允許可變屬性。所有的正常形式首先要求表格是一個關係。根據定義,關係必須有一組固定的屬性。

其他人正在推薦一個EAV表,但EAV中的「值」列不符合具有類型的關係列的定義(其他後果是約束在EAV表中不起作用)。因此EAV表不是一個關係,也不能滿足任何正常的形式。

+0

將序列化屬性放入單個列中也未進行規範化:它違反了第一個標準形式(原子值)。無論如何,用* pure *規範化格式解決這個問題是不可能的。 – 2013-02-17 08:32:46

3

當我在過去遇到過這種情況時,「最佳」答案總是會根據我想要在數據庫中做多少處理,而不是客戶端代碼中的多少處理而變化。

對於什麼是值得的,往往最適合我的方法是每個可選屬性(特別是每個實體類型沒有一個表)。所以,在你的例子上述

assets (as per your example) 
asset_types (as per you example) 
division_assets (as per your example) 
user_assets (as per your example) 
colours 
    asset_id, colour 
weights 
    asset_id, weight 
serial_numbers 
    asset_id, serial_number 

當然,這取決於你需要做出取捨,這可能是你一個不錯的選擇。就我個人而言,我喜歡儘可能保持數據模式,包括數據類型和約束條件,所以下次新屬性出現時,我無法改變表格。

-1

您可以創建兩個新表:

1)下表中定義多個資產屬性(多達資產可能有)

ASSET_ID

asset_attribute

asset_value

2)asset_attribute表

attribute_id

asset_attribute

邏輯將是asset_attributes將需要在asset_attribute表首先定義,然後它可以被用來(連接/標籤)與任何資產(作爲外鍵,從用戶界面上的下拉列表)以及輸入的適當值。

希望這會有所幫助。

相關問題