In welcher Reihenfolge werden ON DELETE CASCADE-Constraints verarbeitet?

8

Hier ist ein Beispiel für das, was ich gemacht habe:

%Vor%

Beachten Sie, dass es für die Onkel-Kind-Beziehung keine ON DELETE CASCADE gibt; d. h. das Löschen eines Child löscht nicht dessen Onkel und umgekehrt.

Wenn ich ein Elternteil und einen Onkel mit demselben Kind habe und ich das Elternteil lösche, scheint es wie InnoDB in der Lage sein sollte, es einfach "herauszufinden" und die Kaskade durch die ganze Familie (dh Löschen des Elternteils löscht auch den Onkel und das Kind). Stattdessen bekomme ich Folgendes:

%Vor%

InnoDB versucht, das Kind vor den Uncle (s), die sich darauf beziehen, in Kaskade zu löschen.

Vermisse ich etwas? Soll das angeblich aus irgendeinem Grund fehlschlagen, verstehe ich nicht? Oder gibt es einen Trick, um es zu funktionieren (oder ist es ein Fehler in MySQL)?

    
Matt Solnit 12.09.2008, 23:46
quelle

4 Antworten

3

Die Eliminierung der Eltern löst die Löschung des Kindes aus, wie Sie es angegeben haben, und ich weiß nicht, warum es vor der Onkertabelle in die Kindtabelle geht. Ich stelle mir vor, Sie müssten sich den dbms-Code ansehen, um sicher zu sein, aber ich bin mir sicher, dass es einen Algorithmus gibt, der auswählt, welche Tabellen zuerst kaskadiert werden sollen.

Das System findet die Dinge, die Sie hier andeuten, nicht wirklich "heraus", und es folgt nur seinen Beschränkungsregeln. Das Problem ist das von Ihnen erstellte Schema, in dem es auf eine Einschränkung stößt, die es nicht weiter passieren lässt.

Ich sehe was du sagst .. wenn es zuerst die Onkel-Tabelle trifft, würde es den Datensatz löschen und dann das Kind löschen (und nicht die Onkel-Kaskade von der Kind-Löschung treffen). Aber ich glaube auch nicht, dass ein Schema erstellt würde, um sich auf diese Art von Verhalten in der Realität zu verlassen. Ich denke, der einzige Weg, um sicher zu wissen, was vor sich geht, ist, durch den Code zu schauen oder einen der mysql / postgresql-Programmierer hier zu holen, um zu sagen, wie er fk-Beschränkungen verarbeitet.

    
Arthur Thomas 16.09.2008, 22:38
quelle
8

Was passiert im einfacheren Fall, wenn ein Datensatz von Child gelöscht wird und er einen verweisenden Onkel hat? Das ist nicht spezifiziert, so dass die Einschränkungen trotzdem fehlschlagen.

Wenn das Löschen eines Childs nicht seine Uncles löscht, was passiert stattdessen? Uncle.childid kann nicht null sein.

Was Sie wollen, ist eines dieser drei Dinge:

  1. Uncle.childid kann null sein und Sie möchten ON DELETE SET NULL für childid.
  2. Uncle.childid kann nicht null sein und Sie möchten ON DELETE CASCADE für childid.
  3. Childid gehört nicht zu Onkel und Sie möchten eine ChildsUncle-Beziehung mit ON DELETE CASCADE-Fremdschlüsselbeschränkungen für Child und Uncle. Uncleid wäre ein möglicher Schlüssel für diese Beziehung (d. H. Sie sollte eindeutig sein).
Apocalisp 13.09.2008 00:08
quelle
0

@Matt Solnit zuerst ist das wirklich eine gute Frage und soweit ich weiß, wenn ein Datensatz von Parent gelöscht werden soll, versucht innodb zuerst herauszufinden, welche anderen Tabellen Referenzen enthalten, damit er den Datensatz löschen kann von ihnen auch. In Ihrem Fall ist es Child Tabelle und Onkel Tabelle, jetzt scheint es, dass in diesem Fall es entscheidet, Datensatz aus Child-Tabelle zuerst zu löschen und damit es den gleichen Prozess für Child wiederholt und schließlich fehlschlägt, da Onkel Verweis auf Child-Tabelle aber weder "ON DELETE CASCADE "noch" ON DELETE SET NULL "wird für FK_child FK in der Uncle-Tabelle angegeben. Es scheint jedoch, dass wenn innodb zuerst versucht, einen Datensatz aus der Uncle-Tabelle zu löschen, dann sollte die Löschung reibungslos verlaufen sein. Nun, nachdem ich einen zweiten Gedanken gegeben habe, denke ich, dass, da innodb dem ACID-Modell folgt, es Child over Uncle wählt, um den Löschprozess zu starten, da es mit Uncle beginnt, selbst wenn die Löschung in Child z. Nehmen Sie eine Friend-Tabelle an, die fk_child-Schlüssel hat (ähnlich wie Uncle), ohne ON DELETE CASCADE, jetzt hätte dies immer noch dazu geführt, dass die gesamte Transaktion fehlgeschlagen ist und daher sieht das für mich richtig aus. In anderen Worten, innodb beginnt mit der Tabelle, die möglicherweise einen Fehler in der Transaktion verursachen könnte, aber das ist meine Theorie in Wirklichkeit könnte es eine ganz andere Geschichte sein. :)

    
sactiw 07.05.2013 17:51
quelle
-1

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

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

    
Tony BenBrahim 13.09.2008 01:02
quelle