在 Rails 開發中,你可能注意到資料庫遷移檔總是建立一個名為 id 的整數欄位作為主鍵。這是 ActiveRecord 的核心慣例之一。雖然使用像訂單編號、ISBN 等具備業務意義的欄位作為主鍵看似直觀,但長遠來看會帶來維護噩夢。
假設以 ISBN 作為 books 表的主鍵。若出版業界決定在所有 ISBN 後附加一位數字,你不僅需更新 books 表的每一筆記錄,還必須處理所有引用該主鍵的外鍵關聯表——這意味著要刪除外鍵約束、批次更新、重建約束,極易出錯且效能低落。
使用無業務意義的代理鍵(如自增整數 id)可完全由資料庫內部控制,隔離外部業務規則變更。即使 ISBN 格式改變,資料庫結構與關聯關係完全不受影響,僅需更新 books 表的 isbn 普通欄位即可。
雖然強烈建議遵循慣例,但在整合現有資料庫時,ActiveRecord 提供 set_primary_key 方法指定自訂主鍵欄位:
class BadBook < ActiveRecord::Base
set_primary_key "isbn"
end
當覆寫主鍵欄位名稱後,ActiveRecord 不再自動產生主鍵值(如自增整數),開發者必須自行確保唯一性。有趣的是,指派主鍵值時仍使用 id 屬性,而非實際欄位名:
book = BadBook.new
book.id = "0-12345-6789" # 使用 id 屬性設定主鍵
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"}
關鍵點:設定主鍵時用 id 屬性,其他操作(如 attributes 回傳)則顯示真實欄位名。
id 整數主鍵慣例,享受零配置與自動管理的便利。set_primary_key 映射現有主鍵,但需自行處理主鍵值指派與唯一性保證。id 欄位作為代理鍵,將原複合鍵改為唯一索引。