与多个表之一相关的数据库列

时间:2014-04-23 07:11:24

标签: mysql sql database

我觉得这是一个非常基本的问题,尽管我已经对数据库做了很多工作,但我仍然无法找到一个很好的方法。谷歌搜索时也似乎无法找到任何东西。

假设我有一堆表,每个表描述一种项目。

例如:

Table candles:
id█  name  █length█diameter▌burntime▌
▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▌
1 █ candle1█54    █  6     █  180   ▌
69█ candle2█29    █  16    █  145   ▌
80█ candle3█100   █ 40     █  110   ▌


Table coasters:
id█  name  █thickness█diameter▌color   ▌
▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀▀▀▀▀▌
1 █coaster1█5        █  20    █#ffffff ▌
6 █coaster2█8        █  41    █#ff0051 ▌
8 █coaster3█7        █ 38     █#002199 ▌


Table baskets:
id█  name  █size█
▀▀█▀▀▀▀▀▀▀▀█▀▀▀▀█
1 █basket1 █5   █
2 █basket2 █8   █
3 █basket3 █22  █

现在我有另一张桌子。我们称之为购物车。此表中的每条记录都需要包含这些项目的数组。这是我不知道如何进行的地方。 所以我需要一对多关系,这意味着我需要一个交汇点/数据透视表。 但是如何?

我应该为每种类型的物品都有一个联结表吗?使用购物车ID的外键和蜡烛/杯垫等的记录ID。 然后,当列出购物车的内容时,我需要检查每个单一的联合表,每种类型的项目都有一个。对我来说听起来不太干净。

或者我应该只有一个单一的联结表,它有一个用于table-name的列和一个用于record-id的列? 看起来也很脏。

我想有更好的方法可以做到这一点,但我想不出来。 该怎么做?

1 个答案:

答案 0 :(得分:0)

解决此问题的一种可能方法是考虑您拥有的项目作为对象,然后考虑如何对这些关系进行建模。如果将所有项目视为具有值的属性对象,则这是存储此信息的常用模式。

这通常被称为O/R Mapping

一个简单的关系示例可能如下所示:

对象 - 定义所有项目

+----+----------+---------+
| Id |   Name   |  Type   |
+----+----------+---------+
|  1 | Candle1  | Candle  |
|  2 | Coaster1 | Coaster |
|  3 | Basket1  | Basket  |
+----+----------+---------+

ObjectProperty - 定义所有属性

+----+-----------+----------+
| Id |   Name    | DataType |
+----+-----------+----------+
|  1 | Length    | Float    |
|  2 | Diameter  | Float    |
|  3 | Burntime  | Float    |
|  4 | Thickness | Float    |
|  5 | Color     | String   |
|  6 | Size      | Int      |
+----+-----------+----------+

ObjectPropertyValue - 定义对象和属性之间的关系,以及值

+----+----------+------------+----------+------------+-----------+-------------+
| Id | ObjectId | PropertyId | ValueInt | ValueFloat | ValueDate | ValueString |
+----+----------+------------+----------+------------+-----------+-------------+
|  1 |        1 |          1 | NULL     | 54.0       | NULL      | NULL        |
|  2 |        1 |          2 | NULL     | 29.0       | NULL      | NULL        |
|  3 |        3 |          6 | 5        | NULL       | NULL      | NULL        |
+----+----------+------------+----------+------------+-----------+-------------+

要检索单个对象的所有值,您可以运行如下查询:

SELECT          OP.Name,
                OP.DataType,
                OPV.ValueInt,
                OPV.ValueFloat,
                OPV.ValueDate,
                OPV.ValueString

FROM            ObjectProperty OP
INNER JOIN      ObjectPropertyValue OPV ON OP.Id = OPV.PropertyId

WHERE           OPV.ObjectId = 1

以这种格式存储信息有几个好处:

  • 它是可扩展的,因此每次新对象时都不需要新表 类型来了
  • 您可以根据需要拥有尽可能多的属性 对象
  • 键入属性值意味着您仍然可以执行相关查询 基于数据类型

即。要搜索长度小于50的所有蜡烛:

SELECT      O.Id, 
            O.Name,
            OP.Name,
            OPV.ValueFloat 
FROM        Object O
INNER JOIN  ObjectPropertyValue OPV ON O.Id = OPV.ObjectId
INNER JOIN  OpjectProperty OP ON OPV.PropertyId = OP.Id

WHERE       OP.Name = 'Length'
AND         O.Type = 'Candle'
AND         OPV.ValueFloat <= 50.0;

然而,也有缺点:

  • 很难在没有动态sql的情况下动态构建查询,因为您首先需要知道要在特定对象上查找的属性类型,然后在ObjectPropertyValue中选择要搜索的相应列
  • 将对象压缩为通用结构有时会使非常简单的操作变得非常复杂。比较在表结构中获取蜡烛与上面的查询相比是多么容易。

还有其他缺点,但是开始详细阅读这个主题的好地方是O/R Mapping and Relational Data

最后,解决这个问题的另一种解决方案是NoSQL, an alternative mechanism to storing objects relationally.

的概念

Jeff Atwood在这个主题上也有一个great article

相关问题