使用 MySQL,从 MyISAM 迁移到 InnoDB 表。数据库设计从转储数据并在没有外键或约束的情况下重新导入数据开始。一次添加一个以查找错误。
我有 ParentTable
,它可以链接到 ChildTableA
或 ChildTableB
,但不能同时链接到两者。 CREATE
语法应该是:(为了简单起见,使用 CREATE
语法而不是多个 ALTER
)
CREATE TABLE `ParentTable`
`IDParentTable` bigint(20) unsigned NOT NULL auto_increment,
`IDChildTableA` bigint(20) unsigned NOT NULL default '0',
`IDChildTableB` bigint(20) unsigned NOT NULL default '0',
PRIMARY KEY (`IDParentTable`),
KEY `ParentTable_IDChildTableA` (`IDChildTableA`),
KEY `ParentTable_IDChildTableB` (`IDChildTableB`)
ENGINE=InnoDB DEFAULT CHARSET=latin1;
不假思索,我尝试包括:
CONSTRAINT `ParentTable_IDChildTableA` FOREIGN KEY (`IDChildTableA`) REFERENCES `ChildTableA` (`IDChildTableA`),
CONSTRAINT `ParentTable_IDChildTableB` FOREIGN KEY (`IDChildTableB`) REFERENCES `ChildTableB` (`IDChildTableB`)
失败了,因为 IDChildTableA
许多行的值为 0,IDChildTableB
许多行的值为 0。但是,没有行两者都为 0。可以看出,IDChildTableA
为 0 时不存在 ChildTableA
,B 也同样如此。
是否有适当的方法来处理这种情况,同时保持引用完整性?不将 ParentTable
一分为二?有没有办法说如果它是 0 或引用有效的相关表就可以?或者,想要多态表是否意味着我必须不受限制?
顺便说一句,我更喜欢这条路线,而不是有一个 IDChildTable
外键,然后有另一列指定它是表 A 还是 B...我认为这对于约束来说并不适用,只是说我宁愿不走那条路...
最佳答案
用作外键的列可以为空。在外键列中使用 NULL 值来指示“未引用行”。
你的外键好像装反了。通常,子表有对父表的引用。
parent (id int primary key)
childA (id int, parent_id int, ...)
childB (id int, parent_id int, ...)
<小时/>
编辑
与引用两个表的外键列(基于鉴别器列)的问题相关......这是不可能的。一个外键约束只能引用一张表。
要实现类似的功能,您需要添加两个单独的外键列,每个外键列引用一个目标表。您可以利用额外的鉴别器列(A 或 B)来识别应使用哪个外键列,因此一个 fk 列将填充有引用,另一个 fk 列将设置为 NULL。
但是,不存在需要填充这两个 fk 列之一的声明性约束。数据库不会强制执行这一点。额外的鉴别器列实际上是多余的,因为您可以根据填充的外键列来派生它。
关于MySQL InnoDB - 将父级链接到两个子级之一的键的约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18563564/