我有一张这样的表:
CREATE TABLE `testt` (
`id` int(11) NOT NULL,
`pid` int(11) DEFAULT NULL,
`active` int(11) NOT NULL DEFAULT '0',
`pacitve` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `id` (`id`,`active`),
KEY `pid` (`pid`,`pacitve`),
CONSTRAINT `active_fk` FOREIGN KEY (`pid`, `pacitve`) REFERENCES `testt` (`id`, `active`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
pid代表父ID
我的数据是这样的:
id pid active pactive
1 NULL 0 0
2 1 0 0
3 1 0 0
4 2 0 0
当我为id = 1设置active = 1时,我得到了这个异常。为什么我收到此错误?删除工作正常。我的目的是当我为id = 1设置active = 1时,所有id = 1的孩子都应该更新。
答案 0 :(得分:8)
问题是你强制执行(pid
,pacitve
)匹配同一个表中的另一条记录,所以对于id 1,你有pid = 1和pacitve = 0,这很好,因为父行具有active = 0.当您更改父行时,不再有相应的行破坏表的完整性。
即使你有CASCADE选项,这些也不适用于引用同一个表的外键(它允许你创建它,但实际上并没有对更新或删除做任何事情)。 documentation states:
如果ON UPDATE CASCADE或ON UPDATE SET NULL递归更新它在级联期间先前已更新的同一个表,它就像RESTRICT一样。这意味着您不能使用自引用ON UPDATE CASCADE或ON UPDATE SET NULL操作。这是为了防止级联更新导致的无限循环。另一方面,自引用ON DELETE SET NULL是可能的,就像自引用ON DELETE CASCADE一样。级联操作可能不会嵌套超过15级。
还要注意,创建一个引用非唯一索引的外键不是标准的,对我来说似乎是一个相当奇怪的偏离标准。然而,文件再次声明:
InnoDB允许外键约束引用非唯一键。这是标准SQL的InnoDB扩展。
您的整个架构设置错误,您根本不需要激活外键引用,也不需要将子状态存储在子节点中,这一切都可以在select中实现。您的表结构应该是:
CREATE TABLE `testt` (
`id` int(11) NOT NULL,
`pid` int(11) DEFAULT NULL,
`active` int(11) NOT NULL DEFAULT '0'
PRIMARY KEY (`id`),
KEY `id` (`id`,`active`),
KEY `pid` (`pid`,`pacitve`),
CONSTRAINT `pid_fk` FOREIGN KEY (`pid`) REFERENCES `testt` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
然后,如果你需要知道父母的状态,你可以使用:
SELECT c.id, c.pid, c.active, p.active AS pactive
FROM testt c
LEFT JOIN testt p
ON c.pid = p.id;
<强> Example before Update 强>
<强> Example after Update 强>