4

这是几个(不完整的)数据库表,用于存储有关酒店房间的信息。它们存储的信息是相同的,但它们的设计不同:

  1. 将楼层信息存储在单独的列中:

    | id | floor 
    |----|-------
    | 1  | 1 
    | 2  | 1 
    | 3  | 2 
    | 4  | 2 
    
  2. 将楼层信息存储在 ID 中。

    | id 
    |-----
    | 101  
    | 102  
    | 201  
    | 202
    

以表 2 的方式将语义数据存储在 ID 中总是一个糟糕的主意,或者是否存在具有更具表现力的 ID 足以证明其合理性的情况?

4

6 回答 6

5

如果要使用自然键,请使用自然键。不要命名自然键id

如果您使用合成键,请将其视为必须唯一但没有其他含义的任意值。

于 2013-03-27T02:21:49.323 回答
3

这实际上与数据的语义无关,而是关于原子性以及您是否会违反 1NF。你应该问自己的问题是:

从数据管理的角度来看,房间号是否应该被视为一个原子数据?

换句话说,您是否总是从数据库中读取(和写入)整个房间号(无论您是否在客户端代码中将其视为一个整体)?

  • 如果是,您可以安全地将其设置为单个属性(如果需要,则将其设置为键或键的一部分)。您是否还会有代理键是另一回事(如下文简要介绍的)。
  • 如果不是(例如:因为您需要查询楼层,或者将楼层用作 FK 等),那么您必须将其拆分为单独的属性(例如楼层 + 每楼层的房间),否则您将违反1NF。

注意:我不知道这是否是故意的,但您的场景 (1) 不包含足够的数据来重建房间号,因此与场景 (2) 相比,它模拟了不同的域。


顺便说一句,将语义数据存储在密钥中本身并不是一个坏习惯。如果某些属性或属性组合必须是唯一的,那么您必须在它们上创建一个键,无论它们是否具有内在含义。您不能用“代理”键替换该键,您只需添加代理(正如您可以想象的那样,它有其优点和缺点)。

于 2013-03-27T02:02:09.217 回答
1

在表的主键中包含语义肯定是个坏主意。

表中主键的用途是:

  • 要独一无二,
  • 用作记录的标识。

如果你把这样的语义放在主键中,那么你假设:

  • 所有房间都有一层,
  • 酒店不会超过一家,
  • 房间号不能有字母。

这些假设在未来很容易分崩离析。然后您将需要更改现有记录的主键 - 这将使它们不再是记录的标识。

这种逻辑也可以应用于其他情况。例如,您可以使用条形码作为书籍的唯一标识符,但将来您可能会拥有没有条形码的书籍。

话虽如此,我什至会更进一步,将您原来的表格更改为id,room_numberfloor. 由于迷信,1301有些酒店没有房间号之类的。1302但这并不意味着他们没有 13 楼。

最后回答你的问题——这可能并不总是一个糟糕的主意,但我想不出一个例子来说明这不是一个坏主意。

于 2013-03-26T22:58:13.110 回答
1

我说是的,这是一个非常糟糕的主意。id 的想法是它是可能替代多列键的行的单列唯一标识符。如果您将列称为“id”,则查看您的架构的任何人都需要一个主键。知道那个东西是地板的表示,你也失去了语义价值。

如果您没有 id 列,并且只需将该列称为“floor”,那就可以了。您关心的是,如果您需要查找特定记录,您能做到吗?如果您的特定应用程序除了查找楼层不需要任何其他信息,则继续使用“楼层”作为列名并且不要添加 ID 列。但是,如果您有一个复合键,例如 floor 和 hotel id,那么您可能希望再次添加 id 列作为“快捷方式”单列键,您可以将其用作其他表中的外键。

于 2013-03-26T23:23:55.517 回答
0

是的,这总是一个糟糕的主意:

  • 如果稍后“价值”发生变化,您也必须更改 ID,这是一个更糟糕的主意
  • 如果您发现必须在具有数字相邻 ID 的两个现有行之间插入一个值的数据,则新 ID 没有空间
  • ID 的目的是唯一标识行。如果 ID coveys 信息,你正在超载它的角色,这在编程中从来都不是一个好主意
  • 如果您将信息隐藏在 ID 中,则必须再次将其提取出来,这会将代码带到任何使用它的地方,这意味着努力和维护
  • 您可能使用的任何框架都将无法使用您的“优化”;他们会期望值在列中,而不是在 ID 的片段中
  • 无论如何,您到底在节省什么?磁盘很便宜,软件/硬件现在这么快,节省的钱可以忽略不计,而且永远不会超过负面影响

我过去自己做过,并且一直后悔这样做,因为你无法预测未来,而业务和数据会以你无法预测的方式发生变化。将自己锁定在任何特定的世界观中都是危险的。事实上,我见过的每一个案例都是这样做的,它会导致很多问题。

于 2013-03-26T23:34:16.673 回答
0

用最重要的数字标识楼层的数字来标识房间绝对没有错。我想我住过的每一家酒店都是这样的。我敢肯定,您的表中必须有这样的房间号属性。

自己和别人的疑惑都是因为你把房间号称为“id”。房间号是一个标识符 - 大概它是唯一真正重要的房间标识符 - 但如果这是您的属性所指的,那么只需将其称为“房间号”,而不是“id”。

于 2017-04-25T19:41:21.427 回答