假设我有一张包含主键a_id
和外键b_id
的表。
a_id
和b_id
永远不会相交很重要,即永远不应该存在a_id = b_id
。
实施此操作的最佳方法是什么?我可以在数据库端(mySql)以某种方式执行此操作,还是应该以编程方式确保?如果我以编程方式确保这一点,那么为主键插入一个数字(而不是让数据库自动增加它)是不好的做法吗?我假设我只是创建一个例程来检查最新的主键并简单地递增它(我还需要确保a_id
的范围永远不会与b_id
的范围相交。有什么建议吗?
答案 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 INSERT
和BEFORE 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的更多信息:
编辑: MySQL目前在其触发器中不支持RAISE
或SIGNAL
,因此我不得不求助于调用不存在的过程ERROR_SELFREFERENCING_ID()
因为它失败了。这会导致INSERT
或UPDATE
失败a_id = b_id
,如果设置无效b_id
,则会大致相同。
答案 4 :(得分:0)
您可以使用GUID s(UUID)作为唯一键。
我在几个项目中使用了它,并且它对于唯一性很有效,尽管它不是最好的索引性能。