SQL - 动态属性

时间:2012-09-25 20:22:29

标签: sql sqlite database-design

我正在尝试创建项目数据库,其中每个项目可以具有多个属性。我还有一个容器表(容器可以容纳物品)。每个容器都有多个必需属性。 item属性必须满足容器属性的要求才能使项目适合容器。

注意:可以随时添加新属性。

Example:
Item 1 Attributes
    Color: Red
    Material: Aluminum
    Length: 100
    Width: 200
    Rating: 4

Container 1 Required Attributes:
    Color=Red
    Material=Aluminum
    Length<105
    Width<300
    Rating=4

我想找到适合容器的所有物品。如果Container Required Attributes表有比较器的字段,我可以获得容器1的所有必需属性,然后根据比较器字段动态生成查询。我不是数据库专家,但这似乎不是一个好的设计。

另一种选择是拥有多个Container Required Attributes表 - 一个用于最大值,一个用于最小值,一个用于等值数字,一个用于等值字符串等。

Example:
Container 1 Maximum Attributes
Length: 105
Width: 300

Container 1 Minimum Attributes
<none>

Container 1 Equal Attributes (Float)
Rating: 4

Container 1 Equal Attributes (String)
Color: Red
Material: Aluminum

在这种情况下,我不必动态生成查询,但这似乎不是最好的解决方案,因为我最终需要表&gt; =和&lt; =。

有没有人对更好的设计有任何建议?

2 个答案:

答案 0 :(得分:1)

当你这样说时:

  

注意:可以随时添加新属性

这会带来很多后果。最初开发的SQL并不是为了支持我称之为“动态数据模型”的东西。在数据模型中发现新但缺失的属性仅由两个事件中的一个引起:信息要求的改变或当前实现中的错误或遗漏的发现。动态数据建模不一定是坏事,但如果你通过抛弃经典数据库管理带来的许多规则来实现它,你就会同时抛出相应的保证。

如果您更进一步,并且说任何用户都可以添加新属性以及添加新数据,那么会产生更多后果。两个用户可能会发现相同的属性,并为其指定不同的名称。这导致“同义词问题”。两个用户可能会发现两个不同的属性,但两者都给出相同的名称。这导致“同音异义问题”。如果你没有解决这些问题,那么从结果数据中理解几乎是不可能的。

我将提醒您在向现有数据库添加新属性方面存在两个重要区别。在SQL级别,它是DDL和DML之间的区别。在数据级别,它是元数据和数据之间的差异。您可能知道大部分内容,但值得根据动态建模重新考虑。

在经典数据库中,实现现有实体或实体之间关系的新发现属性的方式是通过

之类的结构
alter table X add column Y ....

这是DDL。执行DDL的权限通常仅限于DBA,不授予提供数据或将应用程序用作提供数据的接口的用户。所以这个模型在这个意义上不是动态的。 DBA社区(如果有多个DBA)在更改模型之前互相协商。

当您执行类似向现有表添加列的操作时,会发生两件事。首先,改变实际表的结构以适应新列。其次,更新数据字典以反映表的更改。

数据diciotnary包含元数据,描述数据库本身模型的数据。用户表包含描述主题的数据。

通常,当您尝试在SQL中实现动态建模时,最终会在用户表中存储元数据(如列名)的副本。您有责任维护此用户数据与实际数据结构之间的相关性,或它们在数据字典中的反映。

你可以这样做。但这是一项很多工作。而且您正在踏上一段旅程,在这段旅程中,SQL可能不是您前往目的地的最佳方式。

答案 1 :(得分:0)

查询参数只能是表达式,而不是标识符(列)或运算符,因此避免动态生成查询的唯一方法是为所有容器设置一组固定的属性和比较,并仅存储值:

Container 1 Required Attributes:
  Color: Red
  Material: Aliminum
  Max_Length: 105
  Max_Width: 300
  Rating: 4

如果不同的容器具有不同数量或类型的要求,则无论如何您的查询必须是动态的。 在这种情况下,拥有多个必需属性表似乎对单个表没有任何好处。

如果属性存储在列中,您可以通过存储插入WHERE条件的单个字符串(例如items.color='Red' AND items.Length<105 ...)来使设计更加动态。如果您希望以后能够在不解析该字符串的情况下更改某些条件,则必须单独存储条件。