确保主键和外键永不相交的最佳方法是什么?

时间:2009-07-27 23:24:58

标签: mysql database-design primary-key

假设我有一张包含主键a_id和外键b_id的表。

a_idb_id永远不会相交很重要,即永远不应该存在a_id = b_id

实施此操作的最佳方法是什么?我可以在数据库端(mySql)以某种方式执行此操作,还是应该以编程方式确保?如果我以编程方式确保这一点,那么为主键插入一个数字(而不是让数据库自动增加它)是不好的做法吗?我假设我只是创建一个例程来检查最新的主键并简单地递增它(我还需要确保a_id的范围永远不会与b_id的范围相交。有什么建议吗?

5 个答案:

答案 0 :(得分:2)

您可以创建另一个具有自动增量字段的表。插入记录后,它将插入到“密钥表”中并在那里使用引用的值。因此,如果一个表中有两个全局唯一键,则每个插入都是两个键插入。此解决方案也将超过2。

但我不得不问:为什么?

答案 1 :(得分:1)

在Oracle中,您可以使用sequence来实现此行为,该INSERT用于将id分配给两个表中的行。每个表都会在{{1}}上有一个触发器,其中id将从序列中的下一个数字设置。

答案 2 :(得分:1)

您可以设置AUTO_INCREMENT值,使得一个表只有奇数而另一个表只有均数。

这可能非常高效,但它不会为添加另一个唯一密钥的第3个表留下空间。

我不是百分之百确定MySQL,但是使用Oracle你可以定义一个序列,然后只需使用相同的序列来选择你的所有值,这可能是最好的选择(如果它可用于mysql)

答案 3 :(得分:0)

实现此目标的最简单方法是使用CHECK约束。不幸的是,MySQL是MySQL,它不支持CHECK

为了在MySQL中实现相同的效果,您需要创建BEFORE INSERTBEFORE UPDATE触发器以确保两个值都有效。 FK本身负责确保关系有效。这是一个例子:

CREATE TRIGGER upd_check BEFORE UPDATE ON sometable
FOR EACH ROW
BEGIN
    IF NEW.a_id = NEW.b_id THEN
        call ERROR_SELFREFERENCING_ID();
    END IF;
END;

MySQL手册中提供了有关MySQL TRIGGERS的更多信息:

  

18.3.1: Trigger Syntax

编辑: MySQL目前在其触发器中不支持RAISESIGNAL,因此我不得不求助于调用不存在的过程ERROR_SELFREFERENCING_ID()因为它失败了。这会导致INSERTUPDATE失败a_id = b_id,如果设置无效b_id,则会大致相同。

答案 4 :(得分:0)

您可以使用GUID s(UUID)作为唯一键。

我在几个项目中使用了它,并且它对于唯一性很有效,尽管它不是最好的索引性能。