【问题标题】:Type to use for "Status" columns in a sql table用于 sql 表中“状态”列的类型
【发布时间】:2011-11-04 13:05:02
【问题描述】:

我有一个(虚拟)表结构如下:

id: int(11) PK 名称:varchar(255) 状态:?????????

问题是,我应该为状态使用什么数据类型?在我看来,这是我的选择:

  1. varchar 表示状态 - 不好,因为没有完整性
  2. 表示状态的枚举 - 不好,因为要更改值,我必须更改表,然后更改任何带有值下拉列表的代码等
  3. 对状态表进行 int FK - 好是因为它是动态的,坏是因为它更难通过肉眼检查(这可能很有用)
  4. varchar FK 到状态表 - 好,因为它是动态的,并且在检查时可见。不好,因为键是有意义的,这通常是不受欢迎的。有趣的是,在这种情况下,状态表完全有可能只有 1 列,使其成为一个美化的枚举

我对情况有准确的了解吗?拥有一个有意义的密钥真的那么糟糕吗?因为虽然它确实让我起鸡皮疙瘩,但我没有任何理由这样做......

更新: 对于选项 4,建议的结构将是 status: char(4) FK,用于状态表。所以,

打开 => "打开"

CLOS => "关闭"

"PEND" => "待授权"

"PROG" => "进行中

在这种情况下有什么缺点?在这种情况下,我可以看到使用 int 而不是 char 的唯一好处是性能稍差。

【问题讨论】:

  • 离题,应该转移到 DBA SE

标签: sql database join database-design key


【解决方案1】:

我会选择 4 号,但我会使用 char(x) 列。如果您担心性能,char(4) 占用与 int 一样多的空间(或者人们会认为,磁盘 i/o、带宽和处理时间),它也需要 4 个字节来存储。如果您真的担心性能,请将其设为 char(2) 甚至 char(1)。

不要将其视为“有意义的数据”,将其视为自然键的缩写。是的,数据是有意义的,但正如您所注意到的,在处理数据时这可能是一件好事——这意味着您不必总是加入(即使是一个很小的表)来从数据中提取意义数据库。当然,外键约束确保数据有效,因为它必须在查找表中。 (这也可以通过 CHECK 约束来完成,但随着时间的推移,查找表通常更易于管理和维护。)

缺点是你可能会忙于寻找意义。 char(1) 具有很强的吸引力,但如果你得到十个或更多的值,就很难想出 good 有意义的值。 char(4) 的问题不大,但仍然是一个可能的问题。另一个缺点:如果数据可能会更改,那么是的,您的有意义的数据(“PEND” = “Pending Authorization”)可能会失去意义(“PEND” = “Forward to home office for initial approval”)。这是一个糟糕的例子;如果这样的代码确实发生了变化,那么重构系统以反映业务规则的变化可能会更好。我想我的观点应该是,如果它是用户输入的查找值,代理键(整数)将是你的朋友,但如果它们是内部定义和维护的,你绝对应该考虑更人性化的值。那,或者你需要在你的显示器上贴上post-em笔记来提醒你状态= 31应该是什么意思。 (我有三个,而且每隔几个月就会磨损一次。谈谈维护成本......)

【讨论】:

    【解决方案2】:

    使用数字 3。如果您想要可检查的内容,请创建一个加入状态值的视图。

    【讨论】:

    • 使用视图进行检查的好处……似乎很明显。
    【解决方案3】:

    我将使用 INT,并创建与状态表的外键关系。对于枚举状态列,INT 绝对应该是安全的。

    【讨论】:

      【解决方案4】:

      我可以建议您改用 statusID 字段,并有一个单独的表将 ID 映射到 varchar 吗?

      编辑:我想这正是您在第 3 点中概述的内容。我认为这是最好的选择。

      【讨论】:

      • 但这比一个 statusCode 字段有什么好处,仍然映射到一个单独的表?因为一目了然地检查数据更加困难。
      • 就一般设计而言,维护一个映射 ID 和 varchar 之间关系的表要容易得多,然后必须进入每个使用 varchar 的表并相应地进行更改。
      • 我已经更新了问题,希望能更清楚地了解选项 4。它仍然只是编辑 1 个表格来更改描述。
      【解决方案5】:

      我假设您的数据库有一些描述的前端,并且普通用户不会接触到状态代码。

      因此,您的便利仅适用于程序员和 DBA — 重要的人,但我不会为他们优化我的设计。

      更强 - 我会非常小心地使用“有意义”的缩写 - 我见过的最严重的数据错误发生在开发人员清理一些数据并错误地解释“有意义”键时;原来,“PROG”的意思不是“已编程”,而是“进行中”。

      选择选项 3。

      【讨论】:

        【解决方案6】:

        我最近一直在使用许多需要大量状态的数据库,并且我有一些笔记可能值得添加到对话中。

        INT:我发现的一件事是,如果应用程序进行大量跟踪,参考表的数量会很快变得笨拙,并且正如您所提到的,检查数据库乍一看不切实际。 (对于我的一些客户来说,这比在处理时间中节省的几毫秒更重要。)

        VARCHAR:编程的想法很糟糕,但重要的是要考虑给定的状态是否真的会被代码使用,或者只是人眼。对于后者,您可以获得无限范围,并且不必维护任何关系。

        CHAR(4):使用描述性 char 列实际上是一种非常好的方法。我通常只会在价值范围很低且明显时才考虑它,但这只是因为我认为这是一种非标准方法(可能会给新开发者造成混淆)。实际上,您可以将 CHAR 值用作外键,就像使用 INT 一样,获得易读性并保持性能均等。

        我会错过的一件事是数学运算(如“”)。

        INT Range:我尝试过的一种混合策略是使用 INT,但会为数字添加一定程度的语义。所以,例如,

        1-10 being for initial stages, 
        11-20 being in progress, and 
        21-30 being the final stages. 
        60-69 for errors, rejections
        

        这里的问题是,如果你发现你需要更多的数字,你就是 SOL,因为下一个范围已经被占用了。所以,我最终做的是(某种程度上)模仿 HTTP 响应:

        100-199 being for initial stages, 
        200-299 being in progress, and 
        300-399 being the final stages. 
        500-599 for errors, rejections
        

        我更喜欢它而不是简单的 INT,虽然它可能不如 CHAR 描述性强,但它也可以不那么模棱两可。而“PROG”可能意味着很多东西,好的、坏的或良性的,如果我能看到某些东西在 500 范围内,我可能不知道问题是什么,我会告诉你那里是 一个问题。

        【讨论】:

        • 这个答案肯定会得到更多的投票!
        【解决方案7】:

        当您想在 HTML 表单中显示状态列表时,最好创建一个带有状态的单独表格。您可以从查找表中显示详细描述,如果要求是这样的,它将帮助用户选择状态。

        从开发的角度来看,我想将整数作为主键。如果您知道它不会超过限制,则可以使用小/微小整数对其进行优化。

        如果您使用缩写作为外键,那么您必须每次都考虑使其始终独一无二,因为@Philip Kelley 曾提到它的缺点。

        最后,您可以根据需要声明表类型 MISAM。

        更新: 反映@Philip Kelley 的观点,如果状态太多,那么最好使用整数作为外键。如果只有几个状态,则可以使用 abbr 作为外键。

        【讨论】:

          猜你喜欢
          • 2016-12-24
          • 2011-09-13
          • 2013-06-06
          • 1970-01-01
          • 2021-07-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-06-25
          相关资源
          最近更新 更多