Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Restrições de chave estrangeira do MySQL, exclusão em cascata


Se a sua exclusão em cascata excluir um produto porque era um membro de uma categoria que foi eliminada, você configurou suas chaves estrangeiras incorretamente. Dadas suas tabelas de exemplo, você deve ter a seguinte configuração de tabela:
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;

Dessa forma, você pode excluir um produto OU uma categoria, e apenas os registros associados em categorias_produtos morrerão ao lado. A cascata não subirá mais na árvore e excluirá a tabela de produto/categoria pai.

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

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

Se você excluir a categoria 'vermelho', apenas a entrada 'vermelho' na tabela de categorias morre, assim como as duas entradas prod/cats:'botas vermelhas' e 'casacos vermelhos'.

A exclusão não será mais em cascata e não removerá as categorias 'botas' e 'casacos'.

acompanhamento de comentários:

você ainda não está entendendo como as exclusões em cascata funcionam. Eles afetam apenas as tabelas nas quais a "cascata de exclusão" está definida. Neste caso, a cascata é definida na tabela "categories_products". Se você excluir a categoria 'vermelho', os únicos registros que serão excluídos em cascata em Categories_products são aqueles em que category_id = red . Ele não tocará em nenhum registro em que 'category_id =blue' e não seguirá para a tabela "products", porque não há chave estrangeira definida nessa tabela.

Veja um exemplo mais 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 você exclua a categoria #2 (azul):
DELETE FROM categories WHERE (id = 2);

o DBMS examinará todas as tabelas que possuem uma chave estrangeira apontando para a tabela 'categories' e excluirá os registros onde o id correspondente for 2. Como apenas definimos o relacionamento de chave estrangeira em products_categories , você acaba com esta tabela assim que a exclusão for concluída:
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1          | 1           | // red mittens
| 2          | 1           | // red boots
+------------+-------------+

Não há chave estrangeira definida nos products table, então a cascata não funcionará lá, então você ainda tem botas e luvas listadas. Não há mais 'botas azuis' e 'luvas azuis'.