0

好的,所以我现在正在为“Box Items”制作一张表格。

现在,一个盒子项目,取决于它的用途/项目的状态,最终可能与“运输”盒子或“退货”盒子相关。

Box Item 可能有缺陷:如果是,则会在 Box Item 的行中设置一个标志 (IsDefective),并且 Box Item 将被放入“Returns”框中(与其他物品一起退回给该供应商)。否则,Box Item 最终将被放入“Shipping”盒子(与其他要运送的物品一起)。(请注意,运输和退货箱有自己的表格:所有箱子都没有一个公用表格......尽管如果可能的话,我应该考虑这样做作为第三种可能性?)

也许我今天只是想不清楚,但我开始质疑在这种情况下应该怎么做。

我的直觉告诉我,我应该为每个可能的关系设置一个单独的字段,即使在任何给定时间只能发生其中一个关系,这将使 Box Items 的架构看起来像:

BoxItemID 描述 IsDefective ShippingBoxID ReturnBoxID 等...

这将使关系变得清晰,但似乎很浪费(因为任何时候都只会使用其中一个关系)。所以我想我可以只有一个 BoxID 字段,并根据 IsDefective 字段确定它指的是哪个 BoxID(运输或退货箱 ID):

BoxItemID 描述 IsDefective BoxID 等...

这似乎不那么浪费,但不适合我。关系不明显。

所以,我把它交给你,Stackoverflow 的数据库专家。在这个情况下,你会怎么做?

编辑:谢谢大家的意见!它给了我很多思考。一方面,下次我开始这样的项目时,我将使用 ORM。=)两个,因为我现在不在,我会咬四个字节并使用两个字段。

再次感谢大家!

4

7 回答 7

2

我用的是精神病毒液和马特兰特。

走多态路线(必须根据另一个字段的内容确定外键指向哪个表)将是一件痛苦的事情。编码约束可能很困难(我不确定大多数数据库是否会原生支持,我认为你必须使用触发器)。

物品会在桌子之间移动吗?坚持使用两张具有相同定义的表格,一张用于退货,一张用于运输,这可能是最简单的方法。如果您想坚持您首先提出的定义(使用两个单独的字段)是完全合理的。

“过早的优化是万恶之源”等等。虽然看起来很浪费,但请记住您存储的内容。由于它们是 ID,它们可能只是整数,可能是 4 个字节。每条记录浪费四个字节基本上没什么。事实上,由于填充将东西放在偶数地址或其他类似的东西上,将额外的字段放在那里可能是“免费的”。这完全取决于数据库设计。

除非你有充分的理由走多态路线(比如你在一个内存很小的嵌入式系统上,或者你必须通过一些非常慢的 9600bps 链接进行复制),否则你可能不值得为此头疼. 必须将所有这些特殊情况写入查询中会很烦人。

快速示例:在两个表之间进行连接,如果你想连接是基于 isDefective 标志是否设置将是一个痛苦。至少对我而言,仅能单独使用两列中的一列可能就足够省去麻烦了。

于 2008-09-22T02:03:56.637 回答
1

你说的是多态关系。可以引用多个其他表的单个 ID。有几个框架支持这一点,但是,它(可能)对数据库完整性不利(这可能是一个完整的其他讨论,即您的数据库或应用程序是否应该保持引用完整性)。

那这个呢?

BoxItem:
BoxItemID, Description, IsDefective

Box:
BoxID, Description

BoxItemMap:
BoxID, BoxItemID, BoxItemType

然后您可以将 BoxItemType 设为枚举或整数,您可以在其中将应用程序中的常量定义为“Return”或“Shipping”作为盒子的类型。

于 2008-09-22T01:43:29.963 回答
1

我会考虑为盒子制作一个表格,盒子类型是盒子表的一列。这将简化关系并使查询框类型变得容易。所以盒子项目只有一个boxId的外键。

于 2008-09-22T01:49:37.063 回答
1

我会使用 Hibernate 所谓的 Table-per-subclass,所以我的数据库最终会为 Boxes 提供 3 个表:BoxShippingBoxReturnBox. FK inBoxItem将指向Box

于 2008-09-22T08:46:57.153 回答
0

同意上面关于多态性的讨论,虽然它有可能被用得很差,但它仍然是一个可行的解决方案。

基本上,您有一个名为 box 的基表。然后你有另外两个表,装运箱和退货箱。这两个添加了对他们来说特别的任何额外字段。它们与具有 1:1 fk.Boz 基表的 box 相关,具有所有 box 类型的公共字段。

您将 BoxItem 与 box 表相关联。获得正确框类型的方法是执行基于键将子框与根框连接起来的查询。基盒和子盒中都有的记录属于该类型。

您只需要小心,就像提到的那样,当您创建正确完成的框类型时。但这就是测试的目的。添加它们的代码只需要编写一次。或者使用 ORM。

几乎所有的 ORM 都支持这种策略。

于 2008-09-22T01:51:22.067 回答
0

我可能会选择:

BoxTable:
box_id, box_descrip, box_status_id ...
     1, Lovely Box, 1
     2, Borked box, 2
     3, Ugly Box, 3
     4, Flammable Box, 4

       BoxStatus:
       box_status_id, box_status_name, box_type_id, ....
                   1,Shippable, 1
                   2,Return, 2
                   3,Ugly, 2
                   4,Dangerous,3

                BoxType:
                box_type_id, box_type_name, ...
                          1, Shipping box, ...
                          2, Return box, ....
                          3, Hazmat box, ...

这样,Box Status 定义了 box 类型,如果您以后需要扩展到更多的状态级别或 box 类型,它是灵活的。

于 2008-09-22T02:12:55.850 回答
0

我只使用一个 BoxItems 表,其中包含 IsDefective、ShippingBoxID、与运输箱相关的字段、ReturnBoxID 和与退货箱相关的字段。对于每条记录,某些字段将始终为 NULL。

这是一个非常简单且不言而喻的设计,下一个开发人员不太可能被混淆。从理论上讲,这种设计效率低下,因为每行都保证有空字段。在实践中,无论如何,数据库往往对每一行都具有最小所需的存储大小,因此(除非字段数量很大)这种设计无论如何都尽可能高效,并且更容易编码。

于 2008-09-22T02:18:56.523 回答