sql >> Base de Datos >  >> RDS >> Mysql

Restricciones de clave externa de MySQL, eliminación en cascada

Si su cascada elimina un producto nuclear porque era miembro de una categoría que se eliminó, entonces configuró sus claves foráneas incorrectamente. Dadas sus tablas de ejemplo, debería tener la siguiente configuración de tabla:

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;

De esta manera, puede eliminar un producto O una categoría, y solo los registros asociados en categorías_productos morirán al lado. La cascada no viajará más arriba en el árbol y eliminará la tabla principal de productos/categorías.

por ejemplo

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

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

Si elimina la categoría 'roja', solo muere la entrada 'roja' en la tabla de categorías, así como las dos entradas prod/cats:'red boots' y 'red coats'.

La eliminación no seguirá en cascada y no eliminará las categorías 'botas' y 'abrigos'.

seguimiento de comentarios:

todavía no comprende cómo funcionan las eliminaciones en cascada. Solo afectan a las tablas en las que está definida la "cascada al eliminar". En este caso, la cascada se establece en la tabla "categorías_productos". Si elimina la categoría 'roja', los únicos registros que se eliminarán en cascada en categorías_productos son aquellos donde category_id = red . No tocará ningún registro donde 'category_id =blue', y no viajará a la tabla de "productos", porque no hay una clave externa definida en esa tabla.

He aquí un ejemplo más concreto:

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
+------------+-------------+

Digamos que eliminas la categoría #2 (azul):

DELETE FROM categories WHERE (id = 2);

el DBMS buscará en todas las tablas que tienen una clave externa que apunta a la tabla de 'categorías' y eliminará los registros donde la identificación coincidente es 2. Dado que solo definimos la relación de clave externa en products_categories , termina con esta tabla una vez que se completa la eliminación:

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

No hay una clave externa definida en los products mesa, por lo que la cascada no funcionará allí, por lo que todavía tiene botas y guantes en la lista. Ya no hay 'botas azules' ni 'guantes azules'.