外键SQL查询不起作用

时间:2013-12-17 18:03:01

标签: mysql sql foreign-keys

我有一张名为user-friend的表UID and FID. 我有另一个名为user-friend-type的表,它的UID和FID为Foreign key CASCADE,表ID, UID, FID形成主键 问题是如果我发表声明 delete from User-friend where UID=1 and FID=2。它还删除了User-Friend-type中的所有UID = 1,这对我来说非常奇怪。我错过了什么吗?

这里是SHOW创建用户友好型

CREATE TABLE IF NOT EXISTS `userfrnd_source` (
  `id` int(16) NOT NULL AUTO_INCREMENT,
  `userId` int(16) NOT NULL,
  `friendId` int(16) NOT NULL,
  `source_import_Id` int(16) NOT NULL,
  `sourceType` varchar(56) NOT NULL,
  PRIMARY KEY (`id`,`userId`,`friendId`),
  KEY `friendId` (`friendId`),
  KEY `source_import_Id` (`source_import_Id`),
  KEY `ufsource_ufdfk_idx` (`userId`,`friendId`)
)

为用户好友(父母)显示创建

CREATE TABLE IF NOT EXISTS `user_friend_detail` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `userId` int(16) NOT NULL,
  `friendId` int(16) NOT NULL,
  PRIMARY KEY (`id`,`userId`,`friendId`),
  KEY `ufd_users_fk1_idx` (`userId`),
  KEY `ufd_usersfk2_idx` (`friendId`)
)

ALTER TABLE `userfrnd_source`
  ADD CONSTRAINT `userfrnd_source_ibfk_2` FOREIGN KEY (`friendId`) REFERENCES `user_friend_detail` (`friendId`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `userfrnd_source_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `user_friend_detail` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE;

--
-- Constraints for table `user_friend_detail`
--
ALTER TABLE `user_friend_detail`
  ADD CONSTRAINT `ufd_usersfk1` FOREIGN KEY (`userId`) REFERENCES `users` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE,
  ADD CONSTRAINT `ufd_usersfk2` FOREIGN KEY (`friendId`) REFERENCES `users` (`userId`) ON DELETE CASCADE ON UPDATE CASCADE;

引擎为InnoDB

1 个答案:

答案 0 :(得分:0)

感谢您添加DDL,现在可以更清楚地看到发生了什么。

您以非常规的方式定义外键。

“detail”表通常是子表,具有外键的表,并且它引用将成为父表的“type”表。所以你似乎有这些外键倒退 编辑:这原来是我的困惑,因为“细节”通常与子表相关联。

此外,FK应仅引用父表中的PRIMARY KEY或非null UNIQUE KEY中的列。相反,您为每个UID和FID都有一个单独的FK,引用父表中的非唯一二级索引。 InnoDB非常不寻常,因为它允许您定义引用非唯一索引的外键,但这对于SQL来说是非标准的,它可能会导致非常混乱的结果。

此外,每个表都有自己的自动增量ID。这很好,但这意味着子表将没有正确的id值来引用其父表。要解决此问题,您可以为引用的外键定义UNIQUE KEY,而不使用自动增量列。

并确保使用多列外键来匹配它引用的多列唯一键,不要制作两个单列外键,因为它的行为会有所不同。

所以我建议使用以下DDL:

CREATE TABLE IF NOT EXISTS `userfrnd_source` (
  `id` int(16) NOT NULL AUTO_INCREMENT,
  `userId` int(16) NOT NULL,
  `friendId` int(16) NOT NULL,
  `source_import_Id` int(16) NOT NULL,
  `sourceType` varchar(56) NOT NULL,
  PRIMARY KEY (`id`,`userId`,`friendId`),
  KEY `friendId` (`friendId`),
  KEY `source_import_Id` (`source_import_Id`),
  KEY `ufsource_ufdfk_idx` (`userId`,`friendId`)
);

CREATE TABLE IF NOT EXISTS `user_friend_detail` (
  `id` int(8) NOT NULL AUTO_INCREMENT,
  `userId` int(16) NOT NULL,
  `friendId` int(16) NOT NULL,
  PRIMARY KEY (`id`,`userId`,`friendId`),
  UNIQUE KEY `ufd_users_fk1_idx` (`userId`, `friendId`),
  KEY `ufd_usersfk2_idx` (`friendId`)
);

-- change to a single FK constraint, with two columns  
ALTER TABLE `userfrnd_source`
  ADD CONSTRAINT `userfrnd_source_ibfk_2` FOREIGN KEY (`userId`,`friendId`) 
  REFERENCES `user_friend_detail` (`userId`,`friendId`) 
  ON DELETE CASCADE ON UPDATE CASCADE;