数据库设计中的冲突愿望,具有两个相似功能的字段

发布于 2024-07-06 21:36:34 字数 838 浏览 9 评论 0原文

好的,我现在正在为“盒子物品”制作一张表格。

现在,一个盒子物品,根据它的用途/物品的状态,最终可能会与“运输”盒子或“退货”盒子相关。

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

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

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

BoxItemID 描述 有缺陷 运输箱ID 退货箱ID 等等...

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

BoxItemID 描述 有缺陷 盒子ID 等等...

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

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

编辑:谢谢大家的意见! 这给了我很多思考。 首先,下次我开始这样的项目时我将使用 ORM。 =) 对于两个,因为我现在不在,所以我将咬住四个字节并使用两个字段。

再次感谢大家!

Okay, so I'm making a table right now for "Box Items".

Now, a Box Item, depending on what it's being used for/the status of the item, may end up being related to a "Shipping" box or a "Returns" box.

A Box Item may be defective:if it is, a flag will be set in the Box Item's row (IsDefective), and the Box Item will be put in a "Returns" box (with other items to be returned to that vendor). Otherwise, the Box Item will eventually be put into a "Shipping" box (with other items to be shipped). (Note that Shipping and Returns boxes have their own tables: there's not one common table for all boxes... though maybe I should consider doing that if possible as a third possibility?)

Maybe I'm just not thinking clearly today, but I started questioning what should be done in this situation.

My gut tells me that I should have a separate field for each possible relation, even if only one of the relations can happen at any given time, which would make the schema for Box Items look like:

BoxItemID
Description
IsDefective
ShippingBoxID
ReturnBoxID
etc...

This would make the relations clear, but it seems wasteful (since only one of the relations will be used at any time). So then I thought I could have just one field for the BoxID, and determine which BoxID it's referring to (a Shipping or a Returns Box ID) based on the IsDefective field:

BoxItemID
Description
IsDefective
BoxID
etc...

This seems less wasteful, but doesn't sit right with me. The relation isn't obvious.

So, I put it to you, database gurus of Stackoverflow. What would you do in this situation?

EDIT: Thank you everyone for your input! It's given me a lot to think about. For one, I'm going to use an ORM next time I start a project like this. =) For two, since I'm not right now, I'll bite the four bytes and use two fields.

Thanks everyone again!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

偷得浮生 2024-07-13 21:36:34

我和精神病毒液和马特兰在一起。

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

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

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

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

简单的例子:在两个表之间进行连接,如果你想要连接是基于是否设置了 isDefective 标志,这将是一件痛苦的事情。 能够单独使用两列之一可能足以省去很多麻烦,至少对我来说是这样。

I'm with Psychotic Venom and mattlant.

Going the polymorphic route (having to figure out which table your foreign key points to based on the contents of another field) is going to be a pain. Coding the constraints for that maybe tough (I'm not sure most databases would support that natively, I think you'd have to use a trigger).

Do items ever move between the tables? Sticking with two tables with identical definitions where one is for returns and one is for shipping may be the easiest route. If you want to stick with the definition you first proposed (with the two separate fields) is perfectly reasonable.

"Premature optimization is the root of all evil" and all that. While it seems wasteful, remember what you're storing. Since they are IDs they are probably just integers, maybe 4 bytes. Wasting four bytes per record is basically nothing. In fact, due to padding to put things on even addresses or other such things it may be "free" to put that extra field in there. It all depends on the DB design.

Unless you have a very good reason to go the polymorphic route (like you're on an embedded system with little memory or you have to replicate across some really slow 9600bps link) it probably won't be worth the headaches you can end up with. Having to write all those special cases into your queries can get annoying.

Quick example: doing a join between two tables where if you want to join is based on if the isDefective flag is set is going to be a pain. Being able to just use one of the two columns alone is probably enough of a hassle you may save, at least for me.

隔纱相望 2024-07-13 21:36:34

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

I would consider making a single table for the boxes and the box type be a column of the box table. This would simplify the relationships and make it easy to still query for box type. So the box item only has one foreign key to the boxId.

顾冷 2024-07-13 21:36:34

我会使用 Hibernate 所谓的 Table-per-subclass ,所以我的数据库最终会得到 3 个盒子表:BoxShippingBoxReturnBoxBoxItem 中的 FK 将指向 Box

I'd use what Hibernate calls Table-per-subclass, so my DB would wind up with 3 tables for Boxes: Box, ShippingBox, and ReturnBox. The FK in BoxItem would point to Box.

撩动你心 2024-07-13 21:36:34

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

那这个呢?

BoxItem:
BoxItemID, Description, IsDefective

Box:
BoxID, Description

BoxItemMap:
BoxID, BoxItemID, BoxItemType

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

What you're talking about is polymorphic relations. A single ID that can reference multiple other tables. There are several frameworks that support this, however, it is (potentially) bad for database integrity (that could be a whole other discussion whether or not your database or your application should maintain referential integrity).

What about this?

BoxItem:
BoxItemID, Description, IsDefective

Box:
BoxID, Description

BoxItemMap:
BoxID, BoxItemID, BoxItemType

Then you can have BoxItemType be an enumeration, or an integer where you define constants in your application as "Return" or "Shipping" as the type of box.

终止放荡 2024-07-13 21:36:34

同意上面的多态讨论,虽然它有可能使用得不好,但它仍然是一个可行的解决方案。

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

您将 BoxItem 与框表关联起来。 获得正确框类型的方法是执行一个查询,根据键将子框与根框连接起来。 基本框和子框中都有的记录就是这种类型。

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

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

Agree about the polymorphic discussion above, although it has potential to be used poorly, it is still a viable solution.

Basically you have a base table called box. Then you have two other tables, shipping box and return box. Those two add any extra fields that are special to them. they are related to box with a 1:1 fk.Boz base table has the common fields of all box types.

You relate BoxItem with the box table. The way you you get the proper box type is by doing a query that joins the child box with the root box based on the key. The record that has in both the base box and the child box is of that type.

You just have to be careful like mentioned that when you create a box type that it is done correctly. BUt thats what testing is for. The code to add them only needs ot written once. Or use an ORM.

Almost all ORM's support this strategy.

我爱人 2024-07-13 21:36:34

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

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

I'd go with just a single BoxItems table with IsDefective, ShippingBoxID, the shipping-box-related fields, ReturnBoxID and the return-box-related fields. Some fields will always be NULL for each record.

This is a very simple and self-evident design that the next developer is unlikely to be confused by. In theory this design is inefficient because of the guaranteed empty fields for each row. In practice, databases tend to have a minimum required storage size for each row anyway, so (unless the number of fields is huge) this design is as efficient as possible anyway, and much easier to code to.

憧憬巴黎街头的黎明 2024-07-13 21:36:34

我可能会选择:

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, ...

这样,盒子状态定义了盒子类型,如果您稍后需要扩展到更多状态级别或盒子类型,它会很灵活。

I'd probably go with:

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, ...

That way the Box Status defines the box type, and it's flexible if you need to expand into a few more status levels or box types later on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文