无法删除或更新父行:更新父级时外键约束失败

时间:2013-12-31 13:15:11

标签: mysql sql

我有一张这样的表:

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的孩子都应该更新。

1 个答案:

答案 0 :(得分:8)

问题是你强制执行(pidpacitve)匹配同一个表中的另一条记录,所以对于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