문제

다음은 내가 진행 중인 작업의 예입니다.

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;

삼촌-자녀 관계에는 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`))

InnoDB는 그것을 참조하는 Uncle보다 먼저 Child를 계단식 삭제하려고 합니다.

뭔가 빠졌나요?이건가? 추정된 어떤 이유로 실패하는 것이 이해가 안 되나요?아니면 작동하게 만드는 몇 가지 트릭이 있습니까(또는 MySQL의 버그입니까)?

도움이 되었습니까?

해결책

귀하가 언급한 대로 상위 삭제로 인해 하위 삭제가 트리거되고 삼촌 테이블 이전에 하위 테이블로 이동하는 이유를 모르겠습니다.확실히 알기 위해서는 dbms 코드를 살펴봐야 할 것 같지만 먼저 계단식으로 배열할 테이블을 선택하는 알고리즘이 있을 것이라고 확신합니다.

시스템은 실제로 귀하가 여기서 암시하는 방식으로 물건을 '파악'하지 않으며 단지 제약 조건 규칙을 따르고 있습니다.문제는 더 이상 통과할 수 없는 제약 조건이 발생한다는 점에서 생성한 스키마입니다.

무슨 말인지 보니..먼저 삼촌 테이블에 도달하면 레코드를 삭제한 다음 하위 항목을 삭제합니다(그리고 하위 삭제에서 삼촌 캐스케이드에 도달하지 않습니다).하지만 그렇다고 해도 현실에서는 그런 행동에 의존하는 스키마가 마련되지 않을 것 같다.무슨 일이 일어나고 있는지 확실히 알 수 있는 유일한 방법은 코드를 살펴보거나 여기 있는 mysql/postgresql 프로그래머 중 한 명에게 fk 제약 조건을 처리하는 방법을 알려주는 것입니다.

다른 팁

더 간단한 경우, Child에서 레코드가 삭제되고 참조하는 Uncle이 있으면 어떻게 되나요?지정되지 않았으므로 어쨌든 제약 조건이 실패합니다.

Child를 삭제해도 삼촌이 삭제되지 않으면 대신 어떻게 되나요?Uncle.childid는 null일 수 없습니다.

원하는 것은 다음 세 가지 중 하나입니다.

  1. Uncle.childid는 null일 수 있으며 childid에 대해 ON DELETE SET NULL을 원합니다.
  2. Uncle.childid는 null일 수 없으며 childid에 대해 ON DELETE CASCADE를 원합니다.
  3. Childid는 Uncle에 속하지 않으며 Child와 Uncle 모두에 대해 ON DELETE CASCADE 외래 키 제약 조건이 있는 ChildsUncle 관계를 원합니다.Uncleid는 해당 관계에 대한 후보 키가 됩니다(예:고유해야 합니다.)

@Matt Solnit 우선 이것은 정말 좋은 질문입니다. 내가 아는 한, Parent의 레코드가 삭제될 때 innodb는 먼저 해당 테이블에 대한 참조를 보유한 다른 테이블을 식별하여 레코드를 삭제할 수 있도록 시도합니다. 잘.귀하의 경우에는 Child 테이블과 Uncle 테이블입니다. 이제 이 경우 Child 테이블에서 레코드를 먼저 삭제하기로 결정하여 Child에 대해 동일한 프로세스를 반복하고 Uncle이 Child 테이블에 대한 참조를 보유하지만 "ON"이 아니기 때문에 결국 실패하는 것 같습니다. Uncle 테이블의 fk_child FK에 DELETE CASCADE" 또는 "ON DELETE SET NULL"이 지정되었습니다.그러나 그럴 것 같습니다 만약에 innodb는 먼저 Uncle 테이블에서 레코드 삭제를 시도한 다음 삭제가 원활하게 수행되어야 합니다.다시 생각해 본 후 innodb는 ACID 모델을 따르기 때문에 Uncle보다 Child를 선택하여 삭제 프로세스를 시작한다고 생각합니다. 왜냐하면 Uncle로 시작하더라도 Child의 삭제가 여전히 실패했을 수 있기 때문입니다.ON DELETE CASCADE 없이 fk_child 키(Uncle과 유사)가 있는 Friend 테이블을 가정해 보겠습니다. 이제 이로 인해 전체 트랜잭션이 실패하게 되므로 이것이 올바른 동작으로 보입니다.즉, innodb는 트랜잭션 실패를 일으킬 수 있는 테이블로 시작하지만 실제로는 완전히 다른 이야기일 수 있다는 것이 내 이론입니다.:)

디자인이 다 틀려요.문자 그대로 부모 자식 관계가 있는 단일 테이블이 있어야 합니다.그런 다음 쿼리를 사용하여 삼촌(및 이모)을 알아낼 수 있습니다.

select id from persons where -find all children of the grandparents
parent id in (
select parentid from persons --find the grandparents
where id in (
select parentid from persons --find the parents
where id=THECHILD) )
minus --and take out the child's parents
select parentid from persons
where id=THECHILD

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top