如何创建可移动外键?

时间:2011-11-14 14:11:20

标签: sql database database-design relational-database relational-algebra

基本上情况就是这样(简化的伪代码):

我有两个人和国家。

人员表:

KEY INT ID, STRING NAME, STRING COUNTRY

国家/地区表:

KEY INT ID, STRING COUNTRY_NAME

客户端可以控制国家/地区表中的内容,因此他可以添加和删除列表中的县。创建人员时,此国家/地区值会显示在下拉列表中。创建人员时,国家字符串值将插入“人员”行的国家/地区列中。

对我来说,有意义的是,Person应该有一个国家的外键引用,但是因为客户端可以控制Country表中显示的内容,所以它们被保存为单独的表,因为你不能只删除使用过的国家,(参照完整性和所有)。这是我的一位同事在这种情况下不使用外键的论点,但我觉得应该有更好的解决方案来解决这个问题,那么,我的同事是对还是有更好的解决方案?

客户端可以在国家/地区表中添加和删除值,但如果从国家/地区表中删除了值,则使用该值的创建人员应保留其值。

3 个答案:

答案 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,或者是否阻止了引用记录的删除,外键仍然强制执行并保持参照完整性。这是他们的工作,他们非常擅长。