MySQL. Как поддерживать ссылочную целостность при наличии связи многие-ко-многим?
Здравствуйте.
Может быть немного сумбурный вопрос, но, тем не менее, озвучу.
Пытался найти информацию, но не нашел. Про ссылочную целостность много говорится в контексте связей один-к-одному, один-ко-многим, но в контексте связи многие-ко-многим - очень мало. Оно и понятно - в связи один-ко-многим (про один-к-одному не говорю, т.к. используется относительно редко) все очевидно. Есть строка-предок, у которой есть пара - строка-потомок. Потомок без предка не может существовать. Удаляем предка - должен исчезать потомок, обновляем id - он же должен измениться в поле внешнего ключа потомка. Тут и становится нужной возможность поддержания ссылочной целостности средствами движка БД.
Актуально ли, вообще, использование возможностей поддержания ссылочной целостности средствами движка (ON UPDATE, ON DELETE) при использовании связей многие-ко-многим? Для меня не очевиден ни ответ "да", ни ответ "нет".
Можете привести примеры?
Ведь все эти CASCADE, STRICT, etc. работают на паре сущностей, а тут их две.
Для правильного вопроса надо знать половину ответа
Многие-ко-многим реализуется через таблицу отношений. Каждая из двух таблиц сущностей имеет с таблицей отношений связь один-ко-многим. Если удалить запись из одной из таблиц сущностей, то в таблице отношений удалятся соответствующие записи связи.
Уточнение.
В таком случае, у нас ведь получается, технически, что две таблицы по отношению к соединительной являются главными. Но логически одна таблица из двух является главной (ведь при нормализации мы выделяем сущности из основной таблицы в дополнительные), а значит, что мы можем удалить данные из "главной" таблицы и при этом, с помощью средств поддержания ссылочной целостности (ПСЦ) движка, удалится и запись из соединительной таблицы. Но мы не можем удалить данные из "подчиненной" таблицы, покуда на нее ссылается хоть одна строка из "главной", а значит пока есть хоть один внешний ключ в соединительной таблице, ссылающийся на первичный ключ "подчиненной" таблицы. Насколько я понимаю, это будет общепринятой практикой, как правило. Итого, строки касающиеся ПСЦ, при создании соединительной таблицы, будут выглядеть таким образом:
FOREIGN KEY `main_table_id` REFERENCES `main_table` (id) ON UPDATE CASCADE, ON DELETE CASCADE,
FOREIGN KEY `child_table_id` REFERENCES `child_table` (id) ON UPDATE CASCADE, ON DELETE RESTRICT
Я правильно понимаю?
При отношении многие-ко-многим таблицы обычно являются независимыми, без определения главный-дополнительный. Пример - студенты и предметы. Один студент может изучать много предметов, один предмет могут изучать много студентов => соотношение многие-ко-многим. Создаём таблицу связи, включающую id студента и id предмета. Если студент отчислен, то все его связи с предметами в этой таблице нужно удалить. Если предмет исключён из программы, то все связи студентов с этим предметом также надо удалить. То есть обе исходные таблицы сущностей являются главными по отношению к таблице связей, но между собой они независимы.
Да, это тоже один из вариантов - например рецепты блюд. Удалить блюдо можно независимо от того, какие ингридиенты в него входят, а вот удалить ингридиент, входящий хоть в одно блюдо нельзя.
В принципе, таблица связей может перейти в отдельную сущность, например документы движения товаров, когда связь определяет не только какой товар входит в документ, но и количество единиц товара. В этом случае возможен вариант, когда нельзя удалять записи ни в одной из таблиц сущностей пока есть хоть одна связь, иначе нарушается учёт.
Теперь окончательно разобрался. Спасибо. Пришел к очевидному выводу. Возможности поддержания ссылочной целостности - это инструмент. Используется так, как необходимо в рамках здравого смысла. Нет никаких догм.