在Rails Active Record中使用date作为主键

时间:2016-12-28 02:59:01

标签: ruby-on-rails activerecord model primary-key

我在考虑使用日期作为主键而不是跟踪应用程序的标准整数ID,但是,似乎没有那么多支持在rails文档中使用非整数主键。这不赞成吗?我该怎么做?我为什么/不应该考虑它?

2 个答案:

答案 0 :(得分:3)

Rails确实支持使用自定义列作为主键来定义id,据我所知,它可以是字符串或整数类型。

现在,关于您使用日期类型作为主键的计划,有几点需要注意:

主键必须具有这些属性(至少在Rails中):

  • 不能为空
  • 必须是唯一的
  • 有索引

您的日期列是否满足所有这些属性?如果没有,那么放弃你的计划,否则继续阅读......

您必须配置许多内容(不遵循rails默认值)才能使用非id作为主键:

  1. 迁移文件
  2. 模型类
  3. 路线
  4. 控制器
  5. 您可以查看以下链接,获取全面的分步指南: http://ruby-journal.com/how-to-override-default-primary-key-id-in-rails/

    请记住,Rails的咒语是对配置的约定,这意味着通过偏离惯例,您将失去Rails提供的一些优势。如果您接受可能面临的配置和潜在危险,至少要重新考虑使用日期作为列类型的概念,而是选择整数或字符串。

答案 1 :(得分:1)

您正面临着自然(数据派生)和人工(任意值)键的哲学问题。

正如关系理论所阐述的那样, key 与tupple(row)是包含在其中的唯一标识它的数据值的组合。例如:在发票明细行的表格中,发票行的自然键可能是与行号连接的发票号。剩下的数据,产品,数量,单价等都可以通过该密钥唯一访问。

另一种方法是简单地为行分配序列号并将其放在特定字段中,通常名为 id ,与行中包含的数据无关。

哪种方法比较优越?嗯,这取决于很多事情。但是让我们看看给出的例子,发票行的情况。说它是发票20,有10行。我们可以想象一个看起来像这样的键集:000020000001到000020000010。那么,当我们删除第6行时会发生什么?删除具有密钥000020000006的行。

让我们考虑在其上打印发票的行号,以便可以明确地参考未来的客户查询。现在,打印发票时会发生什么?打印发票时,我们是否在行序列中留下间隙,还是将其关闭?如果我们离开差距,那么客户发票上的最后一个发票行将显示10.这将意味着随便的读者发票上有10行。但是第6行不存在,所以发票上只有9行。

另一种方法是在删除后重新编号剩余的行,以便前一行7成为第6行,依此类推。但是,这会更改这三行的键值,这意味着还必须更新对这些行的所有其他引用。这将在任何类型的现实生活系统中产生相当大的开销,并且可能会成为持续的错误来源。

使用人工密钥,id永远不会在数据库外部可见。由于这一次被分配,它需要永远不会改变。因此,如果发票行的密钥是任意值,则可以任意方式自由更新和重新编号发票行,例如按扩展值按降序排序,并且所有内部参考都不受影响。也可以更改发票编号,例如在订购后退商品的情况下。

在关系数据库设计中,通常还没有完全规范化的问题。或者为了获得一个自然的唯一键,涉及到很多tupple的数据,那么tupple本身就成了关键。在这些情况下,自然键或者不能提供必要的独特品质,或者它们的存在使得更新处理成本过高。

实际上,人工密钥已经证明可以提供有保证的唯一密钥,并且与自然密钥相比,在修改包含的数据方面具有最大的灵活性。由于这些原因,人工密钥被广泛使用,并被许多人认为是优越的,或至少是务实的选择。

但是,没有绝对的。在许多情况下,自然键是完全有意义的(例如代码表),并且使用人工id是没有意义的。尽管如此,根据我的经验,如果设计完全使用人工密钥,那么它们将在任何地方使用。

这是RoR采用的方法,出于实际目的,它最有意义。您可以覆盖任意键约定。 AR文档提供了有关如何执行此操作的充分说明。我在某些项目中覆盖了RoR主键,但我从来没有找到真正值得努力的场合。

最后一点。许多人将关系键与索引混淆。关键是关系系统链接集合成员的方法。它不一定是从数据库中检索数据的首选方法。为此目的,人们使用索引,然后仅当维护索引的成本小于通过简单串行搜索的检索速度的增加所获得的益处时。并且索引值不必是唯一的,尽管可以根据需要将其作为约束。