Не стесняйтесь накладывать ограничения на базу данных. Вы обязательно будете иметь согласованную базу данных, и это одна из веских причин использовать базу данных. Особенно, если у вас есть несколько приложений, запрашивающих его (или только одно приложение, но с прямым режимом и пакетным режимом с использованием разных источников).
В MySQL у вас нет расширенных ограничений, как в postgreSQL, но, по крайней мере, ограничения внешнего ключа достаточно продвинуты.
Мы возьмем пример, корпоративную таблицу с пользовательской таблицей, содержащей людей из этой компании
CREATE TABLE COMPANY (
company_id INT NOT NULL,
company_name VARCHAR(50),
PRIMARY KEY (company_id)
) ENGINE=INNODB;
CREATE TABLE USER (
user_id INT,
user_name VARCHAR(50),
company_id INT,
INDEX company_id_idx (company_id),
FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;
Давайте посмотрим на предложение ON UPDATE :
- ОГРАНИЧЕНИЕ ОБНОВЛЕНИЯ : по умолчанию : если вы попытаетесь обновить company_id в таблице COMPANY, механизм отклонит операцию, если хотя бы один ПОЛЬЗОВАТЕЛЬ ссылается на эту компанию.
- ОБНОВЛЕНИЕ НЕТ ДЕЙСТВИЙ : так же, как ОГРАНИЧЕНИЕ.
- ОБ ОБНОВЛЕНИИ КАСКАДА : обычно лучший : если вы обновите company_id в строке таблицы COMPANY, механизм обновит его соответствующим образом для всех строк USER, ссылающихся на эту COMPANY (но триггеры не активированы в таблице USER, предупреждение). Двигатель будет отслеживать изменения для вас, это хорошо.
- ON UPDATE SET NULL : если вы обновите company_id в строке таблицы COMPANY, механизм установит для соответствующих USER company_id значение NULL (должно быть доступно в поле USER company_id). Я не вижу ничего интересного в обновлении, но могу ошибаться.
А теперь на стороне ON DELETE :
- ON DELETE RESTRICT : по умолчанию : если вы попытаетесь удалить идентификатор company_id в таблице COMPANY, механизм отклонит операцию, если хотя бы один пользователь USER хотя бы ссылается на эту компанию, может спасти вам жизнь.
- В УДАЛЕНИИ НЕТ ДЕЙСТВИЙ : так же, как ОГРАНИЧЕНИЕ
- ON DELETE CASCADE : опасно : если вы удалите строку компании в таблице COMPANY, механизм удалит также и соответствующих пользователей. Это опасно, но его можно использовать для автоматической очистки вторичных таблиц (поэтому это может быть то, что вам нужно, но совершенно точно не для примера COMPANY <-> USER)
- ON DELETE SET NULL : handful : если вы удалите строку COMPANY, соответствующие пользователи автоматически будут иметь отношение к NULL. Если значение Null для пользователей без компании, это может быть хорошим поведением, например, может быть, вам нужно сохранить пользователей в вашем приложении как авторов некоторого контента, но удаление компании не является для вас проблемой.
обычно по умолчанию используется: ON DELETE RESTRICT ON UPDATE CASCADE . с некоторыми ON DELETE CASCADE
для таблиц дорожек (журналы - не все журналы - и тому подобное) и ON DELETE SET NULL
когда главная таблица является «простым атрибутом» для таблицы, содержащей внешний ключ, например таблица JOB для таблицы USER.
редактировать
Прошло много времени с тех пор, как я это написал. Теперь я думаю, что я должен добавить одно важное предупреждение. MySQL имеет одно большое документированное ограничение каскадами. Каскады не являются спусковыми механизмами стрельбы . Поэтому, если вы были достаточно уверены в этом движке, чтобы использовать триггеры, вам следует избегать каскадных ограничений.
Триггеры MySQL активируются только для изменений, внесенных в таблицы операторами SQL. Они не активируются ни для изменений в представлениях, ни для изменений в таблицах, сделанных API, которые не передают операторы SQL на MySQL Server
==> См. Ниже последнего редактирования, все движется в этом домене
Триггеры не активируются действиями внешнего ключа.
И я не думаю, что это будет исправлено однажды. Ограничения внешнего ключа управляются хранилищем InnoDb, а триггеры - движком MySQL SQL. Оба разделены. Innodb - это единственное хранилище с управлением ограничениями, возможно, они добавят триггеры непосредственно в механизм хранения данных, а может и нет.
Но у меня есть собственное мнение о том, какой элемент следует выбирать между плохой реализацией триггера и очень полезной поддержкой ограничений внешних ключей. И как только вы привыкнете к согласованности базы данных, вы полюбите PostgreSQL.
12/2017-Обновление этой правки о MySQL:
Как заявил @IstiaqueAhmed в комментариях, ситуация на эту тему изменилась. Поэтому перейдите по ссылке и проверьте реальную актуальную ситуацию (которая может измениться в будущем).
ON DELETE CASCADE : dangerous
- взять со щепоткой соли.SET NULL
вON UPDATE
: обновление компании представляет собой отдел Компании> Отношения пользователя. Например: если компания меняет свой тип бизнеса, предыдущие пользователи больше не могут быть связаны с этим бизнесом, поэтомуNULL
могут быть предпочтительнее для этого индекса.This includes changes to base tables that underlie updatable views
вместо того, что вы вставили то естьThey do not activate for changes in views
CASCADE DELETE
как правило , также хорошо, даже предпочтительнее. Я не считаю это особенно опасным.В дополнение к ответу @MarkR - следует отметить, что многие PHP-фреймворки с ORM не распознают или не используют расширенную настройку БД (внешние ключи, каскадное удаление, уникальные ограничения), что может привести к непредвиденному поведению.
Например, если вы удалите запись, используя ORM, и вы
DELETE CASCADE
удалите записи в связанных таблицах, попытка ORM удалить эти связанные записи (часто автоматически) приведет к ошибке.источник
Вам нужно будет рассмотреть это в контексте приложения. В общем случае вы должны разрабатывать приложение, а не базу данных (база данных просто является частью приложения).
Подумайте, как ваше приложение должно реагировать на различные случаи.
Действие по умолчанию состоит в том, чтобы ограничить (то есть не разрешить) операцию, которая обычно является тем, что вы хотите, поскольку она предотвращает глупые ошибки программирования. Тем не менее, на УДАЛИТЬ КАСКАД также может быть полезным. Это действительно зависит от вашего приложения и от того, как вы собираетесь удалять определенные объекты.
Лично я бы использовал InnoDB, потому что он не удаляет ваши данные (см. MyISAM, который делает), а не потому, что он имеет ограничения FK.
источник