Ich möchte Fremdschlüssel verwenden, um die Integrität zu erhalten und Waisen zu vermeiden (ich verwende bereits innoDB).
Wie erstelle ich eine SQL-Anweisung, die auf CASCADE LÖSCHT?
Wenn ich eine Kategorie lösche, wie stelle ich dann sicher, dass keine Produkte gelöscht werden, die auch mit anderen Kategorien verknüpft sind.
Die Pivot-Tabelle "category_products" erstellt eine Viele-zu-Viele-Beziehung zwischen den beiden anderen Tabellen.
categories
- id (INT)
- name (VARCHAR 255)
products
- id
- name
- price
categories_products
- categories_id
- products_id
mysql
foreign-keys
innodb
Cudos
quelle
quelle
Antworten:
Wenn Ihre Kaskadierung ein Produkt löscht, weil es Mitglied einer Kategorie war, die getötet wurde, haben Sie Ihre Fremdschlüssel nicht ordnungsgemäß eingerichtet. In Anbetracht Ihrer Beispieltabellen sollten Sie die folgende Tabelle einrichten:
Auf diese Weise können Sie ein Produkt ODER eine Kategorie löschen, und nur die zugehörigen Datensätze in category_products sterben daneben. Die Kaskade bewegt sich nicht weiter nach oben und löscht die übergeordnete Produkt- / Kategorietabelle.
z.B
Wenn Sie die Kategorie 'rot' löschen, stirbt nur der Eintrag 'rot' in der Kategorietabelle sowie die beiden Einträge prod / cat: 'rote Stiefel' und 'rote Mäntel'.
Das Löschen wird nicht weiter kaskadiert und die Kategorien "Stiefel" und "Mäntel" werden nicht entfernt.
Kommentar Follow-up:
Sie verstehen immer noch falsch, wie kaskadierte Löschvorgänge funktionieren. Sie wirken sich nur auf die Tabellen aus, in denen die "On Delete Cascade" definiert ist. In diesem Fall wird die Kaskade in der Tabelle "category_products" festgelegt. Wenn Sie die Kategorie 'rot' löschen, sind die einzigen Datensätze, die in Kategorien_Produkten kaskadiert werden, diejenigen, bei denen
category_id = red
. Es werden keine Datensätze berührt, bei denen 'category_id = blue' ist, und es wird nicht zur Tabelle "products" weitergeleitet, da in dieser Tabelle kein Fremdschlüssel definiert ist.Hier ist ein konkreteres Beispiel:
Angenommen, Sie löschen Kategorie 2 (blau):
Das DBMS überprüft alle Tabellen, deren Fremdschlüssel auf die Tabelle 'Kategorien' verweist, und löscht die Datensätze, in denen die übereinstimmende ID 2 lautet. Da wir nur die Fremdschlüsselbeziehung in definiert haben
products_categories
, erhalten Sie diese Tabelle einmal am Löschen abgeschlossen:In der
products
Tabelle ist kein Fremdschlüssel definiert , sodass die Kaskade dort nicht funktioniert. Sie haben also immer noch Stiefel und Fäustlinge aufgelistet. Es gibt nur noch keine "blauen Stiefel" und keine "blauen Fäustlinge" mehr.quelle
CASCADE
betriebsfähig ist. Andernfalls wird der MySQL-Standard MyISAM verwendet und MyISAM unterstützt keineCASCADE
Vorgänge. Fügen Sie dazu einfachENGINE InnoDB
vor dem letzten hinzu;
.Die Antwort auf diese Frage hat mich verwirrt und ich habe einen Testfall in MySQL erstellt. Ich hoffe, das hilft
quelle
Ich denke (ich bin nicht sicher), dass Fremdschlüsseleinschränkungen angesichts Ihres Tabellendesigns nicht genau das tun, was Sie wollen. Am besten definieren Sie eine gespeicherte Prozedur, mit der eine Kategorie nach Ihren Wünschen gelöscht wird, und rufen diese Prozedur dann auf, wenn Sie eine Kategorie löschen möchten.
Sie müssen der Verknüpfungstabelle auch die folgenden Fremdschlüsseleinschränkungen hinzufügen:
Die CONSTRAINT-Klausel kann natürlich auch in der Anweisung CREATE TABLE enthalten sein.
Nachdem Sie diese Schemaobjekte erstellt haben, können Sie eine Kategorie löschen und das gewünschte Verhalten erhalten, indem Sie Folgendes ausgeben
CALL DeleteCategory(category_ID)
(wobei category_ID die zu löschende Kategorie ist). Das Verhalten verhält sich dann wie gewünscht. Geben Sie jedoch keine normaleDELETE FROM
Abfrage aus, es sei denn, Sie möchten mehr Standardverhalten (dh nur aus der Verknüpfungstabelle löschen und dieproducts
Tabelle in Ruhe lassen).quelle
KEY pkey (product_id),
die dritteCREATE TABLE
Abfrage in der akzeptierten Antwort bedeutet?