基本上情况就是这样(简化的伪代码):
我有两个人和国家。
人员表:
KEY INT ID, STRING NAME, STRING COUNTRY
国家/地区表:
KEY INT ID, STRING COUNTRY_NAME
客户端可以控制国家/地区表中的内容,因此他可以添加和删除列表中的县。创建人员时,此国家/地区值会显示在下拉列表中。创建人员时,国家字符串值将插入“人员”行的国家/地区列中。
对我来说,有意义的是,Person应该有一个国家的外键引用,但是因为客户端可以控制Country表中显示的内容,所以它们被保存为单独的表,因为你不能只删除使用过的国家,(参照完整性和所有)。这是我的一位同事在这种情况下不使用外键的论点,但我觉得应该有更好的解决方案来解决这个问题,那么,我的同事是对还是有更好的解决方案?
客户端可以在国家/地区表中添加和删除值,但如果从国家/地区表中删除了值,则使用该值的创建人员应保留其值。
答案 0 :(得分:1)
您可以指定FOREIGN KEY
删除引用表记录时的内容:ON DELETE ([RESTRICT | CASCADE | SET NULL | NO ACTION])
(这些是MySQL中提供的选项)。
通常,您应该使用外键。例如,如果有人提到国家,为什么还可以删除一个国家?如果没有外键,您需要手动检查参考。
在您的示例中,我还会使用国家/地区的ID字段作为参考。您可以更改国家/地区的名称,所有引用该ID的人都将获得此信息(当然,您需要加入)。
此更新的另一个解决方案是为原始外键指定ON UPDATE CASCADE
选项,从而在更改国家/地区名称时更新相应人员的所有Country
字段。< / p>
答案 1 :(得分:1)
创建一个isactive列,历史记录的数据将显示orginally选择的县(或更新后的值,见下文),下拉列表可以调整为仅显示活动国家/地区。在任何情况下都不应删除外键约束。这是数据完整性问题的一个方法。
设置为null的想法通常也很糟糕。您不希望丢失有关该人所在国家/地区的数据。
如果国家/地区可能会发生变化(而不是添加新国家/地区),那么您可以使用级联更新,但在这种情况下最好使用代理键(不应更改)。然后,如果名称被更改,它将反映在任何地方,而无需更新数百万个子记录。
答案 2 :(得分:0)
数据库已设计用于处理仍由外键引用的记录的删除。
您仍然应该使用外键,并指定您希望它与on delete
的行为方式。如果您想要删除仍被引用(按人员)的记录(国家/地区),请使用
foreign key country_id references countries(id)
on delete set null;
如果您希望阻止引用的国家/地区的外键消失,请取消on delete
子句并尝试删除仍然引用的国家/地区将失败。这通常是期望的行为;尝试将数据库置于无效状态应该失败。
相关记录的foriegn密钥是否设置为null
,或者是否阻止了引用记录的删除,外键仍然强制执行并保持参照完整性。这是他们的工作,他们非常擅长。