1

我遇到了 Rails 3.2 关联和 PostgreSQL 外键之间的细微差别,我想确定我了解管理它的最佳方法。

假设一个 Message 类跟踪它正在回复的消息。删除“来自”消息不应删除链中的其余消息,因此没有:dependent => :destroy子句。

class Message < ActiveRecord::Base
  # from_message_id self-reference
  has_many   :from_messages, :foreign_key => "from_message_id", 
             :class_name => "Message", :inverse_of => :from_message
  belongs_to :from_message, 
             :class_name => "Message", :inverse_of => :from_messages

  attr_accessible :from_message_id, subject, body
end

现在,如果我创建两个链接的消息,并删除第一个,Rails 只会报告它不存在:

m1 = Message.create
m2 = Message.new
m2.from_message = m1
m2.save
m1.destroy
m2.from_message
=> nil

但是,如果我还从迁移中向数据库添加了一个实际的外键约束:

execute "ALTER TABLE messages ADD CONSTRAINT messages_from_message_fk 
         FOREIGN KEY (from_message_id)  REFERENCES messages(id);"

然后我得到一个相当讨厌的中止,因为密钥仍在使用中:

m1 = Message.create
m2 = Message.new
m2.from_message = m1
m2.save
m1.destroy
=> ActiveRecord::InvalidForeignKey: PG::Error: ERROR:  update or delete on table 
"messages" violates foreign key constraint "messages_from_message_fk" on 
table "messages"
DETAIL:  Key (id)=(2) is still referenced from table "messages".

这些结论正确吗?

  • Rails 仅使用has_manyandbelongs_to来跟踪哪些字段包含哪些外键。删除“父”记录时,不会验证子记录不会成为孤立记录。

  • 具有外键约束的 PostgreSQL 要求在删除父级之前,所有子级都与父级“取消链接”。只要外键可以为空,这可以通过在删除父级之前将子级的外键设置为空来实现。

就我而言,我允许孤儿。我最好忘记数据库约束,还是在删除父项时保留它并取消链接记录有什么价值?

4

1 回答 1

0

就我而言,我想允许孤儿。我最好忘记数据库约束,还是在删除父项时保留它并取消链接记录有什么价值?

在 PostgreSQL 中,通过删除外键约束来更改表,然后使用 ON DELETE SET NULL 重新添加它;在这种情况下,删除将级联到将外键设置为空,从而允许孤儿。

于 2013-04-02T11:03:48.760 回答