处理ON DELETE CASCADE约束的顺序是什么?

Mat*_*nit 10 mysql database-design mysql-error-1451

这是我发生的事情的一个例子:

CREATE TABLE Parent (id BIGINT NOT NULL,
  PRIMARY KEY (id)) ENGINE=InnoDB;

CREATE TABLE Child (id BIGINT NOT NULL,
  parentid BIGINT NOT NULL,
  PRIMARY KEY (id),
  KEY (parentid),
  CONSTRAINT fk_parent FOREIGN KEY (parentid) REFERENCES Parent (id) ON DELETE CASCADE) ENGINE=InnoDB;

CREATE TABLE Uncle (id BIGINT NOT NULL,
  parentid BIGINT NOT NULL,
  childid BIGINT NOT NULL,
  PRIMARY KEY (id),
  KEY (parentid),
  KEY (childid),
  CONSTRAINT fk_parent_u FOREIGN KEY (parentid) REFERENCES Parent (id) ON DELETE CASCADE,
  CONSTRAINT fk_child FOREIGN KEY (childid) REFERENCES Child (id)) ENGINE=InnoDB;
Run Code Online (Sandbox Code Playgroud)

请注意,Uncle-Child关系没有ON DELETE CASCADE; 即删除子项不会删除其叔叔,反之亦然.

当我有一个父母和一个叔叔同一个孩子,并且我删除了父母时,似乎 InnoDB应该能够"搞清楚"并让级联涟漪通过整个家庭(即删除父母删除叔叔)和孩子一样).但是,我得到以下内容:

  ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`cascade_test/uncle`, CONSTRAINT `fk_child` FOREIGN KEY (`childid`) REFERENCES `child` (`id`))
Run Code Online (Sandbox Code Playgroud)

InnoDB试图在引用它的叔叔之前级联删除Child.

我错过了什么吗?难道这应该失败由于某种原因,我不明白?或者是否有一些技巧使其工作(或者它是MySQL中的错误)?

Apo*_*isp 8

在更简单的情况下,如果从Child删除记录并且它具有引用Uncle会发生什么?这是未指定的,因此无论如何约束都失败了.

如果删除子项不删除其Uncles,那么会发生什么?Uncle.childid不能为空.

你想要的是这三件事之一:

  1. Uncle.childid可以为null,并且您希望为childid启用ON DELETE SET NULL.
  2. Uncle.childid不能为null,并且您想为childid启用ON DELETE CASCADE.
  3. Childid不属于Uncle,并且您希望ChildsUncle与ON DELETE CASCADE外键约束关系到Child和Uncle.Uncleid将是该关系的候选键(即它应该是唯一的).


Art*_*mas 3

正如您所说,父删除正在触发子删除,我不知道为什么它会在叔叔表之前进入子表。我想您必须查看 dbms 代码才能确定,但​​我确信有一个算法可以选择首先级联到哪些表。

系统并没有真正按照您在这里暗示的方式“弄清楚”东西,它只是遵循其约束规则。问题是您创建的模式遇到了不允许它进一步通过的约束。

我明白你在说什么..如果它首先命中叔叔表,它将删除该记录,然后删除子项(并且不会从子项删除中命中叔叔级联)。但即便如此,我认为不会建立一个模式来依赖现实中的这种行为。我认为确定发生了什么的唯一方法是查看代码或让这里的 mysql/postgresql 程序员之一说明它如何处理 fk 约束。