sql >> Database >  >> RDS >> Mysql

MySQL-beperkingen voor externe sleutels, trapsgewijs verwijderen

Als je trapsgewijze nuke een product verwijdert omdat het lid was van een categorie die is gedood, dan heb je je externe sleutels onjuist ingesteld. Gezien uw voorbeeldtabellen, zou u de volgende tabelconfiguratie moeten hebben:

CREATE TABLE categories (
    id int unsigned not null primary key,
    name VARCHAR(255) default null
)Engine=InnoDB;

CREATE TABLE products (
    id int unsigned not null primary key,
    name VARCHAR(255) default null
)Engine=InnoDB;

CREATE TABLE categories_products (
    category_id int unsigned not null,
    product_id int unsigned not null,
    PRIMARY KEY (category_id, product_id),
    KEY pkey (product_id),
    FOREIGN KEY (category_id) REFERENCES categories (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE,
    FOREIGN KEY (product_id) REFERENCES products (id)
       ON DELETE CASCADE
       ON UPDATE CASCADE
)Engine=InnoDB;

Op deze manier kunt u een product OF een categorie verwijderen, en alleen de bijbehorende records in categorieën_producten zullen ernaast verdwijnen. De cascade gaat niet verder omhoog in de boom en verwijdert de bovenliggende product-/categorietabel.

bijv.

products: boots, mittens, hats, coats
categories: red, green, blue, white, black

prod/cats: red boots, green mittens, red coats, black hats

Als u de categorie 'rood' verwijdert, sterft alleen het 'rode' item in de categorieëntabel, evenals de twee items prod/cats:'rode laarzen' en 'rode jassen'.

Het verwijderen gaat niet verder en verwijdert de categorieën 'laarzen' en 'jassen' niet.

reactie follow-up:

je begrijpt nog steeds niet hoe trapsgewijze verwijderingen werken. Ze zijn alleen van invloed op de tabellen waarin de "cascade bij verwijderen" is gedefinieerd. In dit geval wordt de cascade ingesteld in de tabel "categories_products". Als u de categorie 'rood' verwijdert, zijn de enige records die trapsgewijs worden verwijderd in categorieën_products die waarbij category_id = red . Het zal geen records raken waar 'category_id =blue', en het zou niet verder reizen naar de "producten"-tabel, omdat er geen externe sleutel is gedefinieerd in die tabel.

Hier is een meer concreet voorbeeld:

categories:     products:
+----+------+   +----+---------+
| id | name |   | id | name    |
+----+------+   +----+---------+
| 1  | red  |   | 1  | mittens |
| 2  | blue |   | 2  | boots   |
+---++------+   +----+---------+

products_categories:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 1          | 2           | // blue mittens
| 2          | 1           | // red boots
| 2          | 2           | // blue boots
+------------+-------------+

Stel dat u categorie #2 (blauw) verwijdert:

DELETE FROM categories WHERE (id = 2);

het DBMS zal naar alle tabellen kijken die een refererende sleutel hebben die naar de 'categorieën'-tabel verwijst, en de records verwijderen waar de overeenkomende id 2 is. Omdat we de relatie met de refererende sleutel alleen hebben gedefinieerd in products_categories , krijg je deze tabel zodra het verwijderen is voltooid:

+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 2          | 1           | // red boots
+------------+-------------+

Er is geen externe sleutel gedefinieerd in de products tafel, dus de cascade zal daar niet werken, dus je hebt nog steeds laarzen en wanten op de lijst. Er zijn gewoon geen 'blauwe laarzen' en geen 'blauwe wanten' meer.



  1. Hoe MySQLdb gebruiken met Python en Django in OSX 10.6?

  2. Inzicht in de unieke beperkingen van SQL Server

  3. Veldnamen ophalen uit tijdelijke tabel (SQL Server 2008)

  4. tabelnaam doorgeven als plsql-parameter