Frage

Hier ist ein Beispiel dafür, was ich habe, los:

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;

Beachten Sie kein ON CASCADE für die Onkel-Kind-Beziehung DELETE ist; das heißt ein Kind zu löschen löscht nicht seinen Onkel (n) und umgekehrt.

Wenn ich ein Elternteil und ein Onkel mit demselben Kind haben, und ich die Eltern löschen, es scheint wie sollte InnoDB der Lage sein, nur „es herausfinden“ und lassen Sie die Kaskade durch die Welligkeit ganz Familie (dh die Mutter Löschen löscht den Onkel und das Kind als auch). Doch statt, erhalte ich die folgenden:

  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 versucht, das Kind vor dem Onkel (n), die sie beziehen sich auf Kaskade löschen.

Bin ich etwas fehlt? Ist das sollte aus irgendeinem Grund scheitern Ich verstehe nicht? Oder gibt es einen Trick, um damit es funktioniert (oder ist es ein Bug in MySQL)?

War es hilfreich?

Lösung

Die Mutter Löschen wird das Auslösen des Kind Löschen wie Sie sagen, und ich weiß nicht, warum es das Kind Tisch vor dem Onkel Tisch geht. Ich denke, Sie würden am dbms Code aussehen müssen, um sicher zu wissen, aber ich bin sicher, es ist ein Algorithmus, der die Tabellen nimmt Kaskade zum ersten.

Das System wirklich nicht ‚herausfinden‘ stopfen, wie Sie hier bedeuten, und es wird nur nach ihrer Einschränkung Regeln. Das Problem ist das Schema, das Sie erstellt, dass sie eine Einschränkung trifft, die nicht weiter passieren lassen.

Ich sehe, was Sie sagen .. wenn es den Onkel Tisch zuerst getroffen würde es den Datensatz löscht und dann das Kind löschen (und nicht den Onkel Kaskade von dem Kind Löschung getroffen). Aber auch so, glaube ich nicht, ein Schema auf dieser Art von Verhalten in der Realität verlassen würde einzurichten. Ich denke, der einzige Weg, um sicher zu wissen, was los ist, ist durch den Code zu suchen oder in hier eine der mysql / postgresql Programmierer erhalten zu sagen, wie es fk Einschränkungen verarbeitet werden.

Andere Tipps

Im einfacheren Fall, was passiert, wenn ein Datensatz von Child gelöscht und es hat eine Referenzierung Onkel? Das ist nicht spezifiziert, so die Beschränkungen nicht für die ohnehin.

Wenn ein Kind das Löschen nicht seine Uncles löschen, was geschieht dann statt? Uncle.childid kann nicht null sein.

Was Sie wollen, ist eine dieser drei Dinge:

  1. Uncle.childid kann null sein, und Sie wollen sich auf NULL DELETE SET für childID.
  2. Uncle.childid kann nicht null sein, und Sie wollen ON DELETE CASCADE für childID.
  3. childID gehört nicht auf Onkel, und Sie wollen eine ChildsUncle Beziehung mit ON CASCADE Fremdschlüssel-Constraints sowohl Kind und Onkel DELETE. Uncleid wäre ein Kandidat Schlüssel für diese Beziehung sein (das heißt, es sollte eindeutig sein).

@ Matt Solnit erste von all dem ist wirklich eine gute Frage und soweit ich weiß, wenn ein Datensatz von Eltern gelöscht werden soll dann zuerst versucht InnoDB die anderen Tabellen hält Verweise darauf zu identifizieren, so dass es den Datensatz löschen von ihnen als gut. In Ihrem Fall es Kindertisch und Onkel Tisch, jetzt scheint es, dass in diesem Fall entscheidet er zum ersten Datensatz aus Child-Tabelle zu löschen und so wiederholen sie den gleichen Prozess für Kinder- und scheitert schließlich als Onkel Bezug auf Kindertisch hält aber weder „ON DELETE CASCADE“oder "ON SET NULL LÖSCHEN" wird für fk_child FK in Onkel Tabelle angegeben. Allerdings ist es nicht scheint, dass , wenn innodb ersten Datensatz aus dem Onkel Tabelle zu löschen versucht, dann sollte Löschung reibungslos geschehen. Nun, nachdem einen zweiten Gedanken Ich denke, dass da innodb ACID-Modell folgt damit es Kind über Onkel wählt den Löschvorgang zu starten becuase wenn es mit Onkel beginnt auch dann die Löschung in Kind noch versagt haben könnte z.B. An einen Freund Tabelle annimmt, dass dies gut aussieht Verhalten mir fk_child hat, wäre dies nun CASCADE-Taste (ähnlich wie Onkel) ohne ON DELETE noch die gesamte Transaktion zu scheitern und damit verursacht. In anderen Worten innodb beginnt mit Tabelle, die einen möglichen Fehler in der Transaktion führen kann, aber das ist meine Theorie in Wirklichkeit könnte es eine ganz andere Geschichte sein. :)

das Design ist alles falsch. Sie sollten einzelne Tabelle haben, mit Eltern-Kind-Beziehung (brettert). Dann können Sie herausfinden, Onkel (und Tanten) mit einer Abfrage

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top