主键与ID

  • Post author:
  • Post category:其他


你可能已经注意到了我们的例子数据库内的所有表都定义有一个整数列叫id,做为表的

主键。这是Active Record 的约定。

“请等等!”你喊道。“我的order 表的主键应该是定单号或一些意义的列?为什么使

用一个没有意义的主键,比如id?”

原因是实践—外部数据的格式可能随着时间而更改。例如,你可能想一本书的ISBN 应该

是books 表的最好主键。毕竟,ISBN 是唯一的。但是像现在写的这本书,美国的发行行业做

了修改,给所有的ISBN 一个额外的数字。

如果我们已使用ISBN 做books 表的主键,我们必须更改每一行以反映这种改变。但是会

有另一个问题。数据库内所有的通过books 表的主键引用它的其它表呢。我们不能修改books

表内这些键,除非我们先遍历它,然后更新所有这些引用。而且这还包括使用的外键约束,

更新表,更新books 表,最后重建约束。所有这些,是多大的痛苦。

如果我们使用我们自己的内部值做为主键,则事情会工作的更好。没有第三方跟着,也

不会武断的要求我们修改什么—我们控制我们自己的键空间。如果有些事如ISBN 需要修改,

它的修改不会影响到数据库内任何其它现有的关联。实际小,我们已经将这些行内数据的外

部表示与行的关系减到了最小。

现在,没有什么理由说我们不能给我们的终用户使用id 值了。在order 表内,我们可以

称它为一定单的id,并在所有工作簿上打印它。但是做这些事要小心—在任何时候一些调整

可能发生并要求定单的id 必须遵循一个外部施加的格式,并且你要返回你开始的地方。

如果你给一个Rails 应用程序创建了一个新schema,你或许想与工作流配合,并给你的

所有表一个id 列做为它们主键。[我们稍后会看到,join 表不包含这一点—它们不应该有一

个id 列。]如果你需要用一个现有的schema 工作,Active Record 给你一个简单的途径来为

一个表重写主键的缺省名字。

class BadBook < ActiveRecord::Base

set_primary_key “isbn”

end

通常,Active Record 接受创建的新主键值给你创建的记录并添加到数据库中—它们将

升序的整数(或许是有一定间隔的序列)。但是,如果你重写主键列的名字,你也要接受一个

职责,在你保存新行之前,你要设置主键一个唯一值。或许令人惊讶的是,你还设置一个属

性叫id 来做这些。直到Active Record 被关心,主键属性总是被设置为一个叫id 的属性。

set_primary_key 声明设置用于表的列名字。下面例子代码中,我们使用一个叫id 的属性,

即使数据库内的主键是ISBN。

book = BadBook.new

book.id = “0-12345-6789”

book.title = “My Great American Novel”

book.save

# …

book = BadBook.find(“0-12345-6789”)

puts book.title # => “My Great American Novel”

p book.attributes #=> {“isbn” =>”0-12345-6789″,

“title”=>”My Great American Novel”}

刚才做的事情有些乱,model 对象的属性有个isbn 列和title 列—id 没有出现。当我们

需要设置主键时,使用id。在所有其它时候,使用实际的列名。