我有一张这样的桌子:
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
Run Code Online (Sandbox Code Playgroud)
pid代表父ID
我的数据是这样的:
id pid active pactive
1 NULL 0 0
2 1 0 0
3 1 0 0
4 2 0 0
Run Code Online (Sandbox Code Playgroud)
当我为id = 1设置active = 1时,我得到了这个异常.为什么我收到此错误?删除工作正常.我的目的是当我为id = 1设置active = 1时,应该更新id = 1的所有子节点.
问题是你已经强制(pid,pacitve)匹配同一个表中的另一个记录,所以对于id 1,你有pid = 1和pacitve = 0,这很好,因为父行有活动= 0.当你改变父行中不再有相应的行破坏表的完整性.
即使你有CASCADE选项,这些也不适用于引用同一个表的外键(它允许你创建它,但实际上并没有对更新或删除做任何事情).该文档状态:
如果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;
Run Code Online (Sandbox Code Playgroud)
然后,如果您需要知道父级的状态,您可以使用:
SELECT c.id, c.pid, c.active, p.active AS pactive
FROM testt c
LEFT JOIN testt p
ON c.pid = p.id;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8767 次 |
| 最近记录: |