2013-02-17 81 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表首先定义,然后它可以被用来(连接/标签)与任何资产(作为外键,从用户界面上的下拉列表)以及输入的适当值。

希望这会有所帮助。

相关问题