MySQL: внешний ключ, ссылающийся на двух родителей - PullRequest
2 голосов
/ 04 февраля 2010

У меня интересная ситуация: у меня есть внешний ключ от a.name (дочерняя таблица) до b.name (родительская таблица). b.name не имеет уникальных ограничений, поэтому может содержать повторяющиеся значения.

Если я добавлю имя 'bob' в b.name дважды , а затем добавлю его в a.name, я больше не смогу удалить или обновить либо экземпляр 'bob 'в таблице б. В обоих случаях он жалуется, что при удалении / обновлении строки в таблице b FKey, связывающий a.name с b.name, завершится неудачей.

Теперь это имеет некоторый смысл, но я хочу, чтобы FKey мог потерпеть неудачу только в том случае, если в таблице b есть no другой экземпляр 'bob'. Поэтому, если у меня есть несколько экземпляров 'bob' в b.name, я могу изменить / удалить любой, кроме последнего.

[Обратите внимание, что выполнение очевидного и добавление уникального ограничения для b.name не будет работать, потому что это приведет к «неопределенному поведению» в приложении, которое я не писал]

Есть идеи?

Ответы [ 4 ]

2 голосов
/ 04 февраля 2010

Прямо от http://dev.mysql.com/doc/refman/5.1/en/innodb-foreign-key-constraints.html

...Additionally, MySQL and InnoDB require that the referenced columns be indexed for performance. However, the system does not enforce a requirement that the referenced columns be UNIQUE or be declared NOT NULL.The handling of foreign key references to nonunique keys or keys that contain NULL values is not well defined for operations such as UPDATE or DELETE CASCADE. You are advised to use foreign keys that reference only UNIQUE and NOT NULL keys....

Итак, держите свои ФК привязанными к уникальным ценностям или кто скажет, что происходит?

0 голосов
/ 04 февраля 2010

Хотя ваша ситуация далека от оптимальной или даже рекомендуется, вы можете обойти проверки внешнего ключа следующим образом:

SET FOREIGN_KEY_CHECKS = 0;
// do your dirty work here
SET FOREIGN_KEY_CHECKS = 1;

Вы должны будете поддерживать ссылочную целостность в своем коде, как вы описали в своем посте.

0 голосов
/ 04 февраля 2010

Если вы поместите 'bob' в b.name дважды, то он больше не будет однозначно идентифицироваться как строка в таблице b.

Если ваше требование состоит в том, чтобы b.name могло иметь повторяющиеся значения, тогда ваша таблица должна использовать лучший ключ (суррогатный ключ или составной ключ).

Помимо проблемы обновления / удаления, такие запросы, как SELECT * FROM a join b on a.name = b.name, также не будут работать должным образом.

0 голосов
/ 04 февраля 2010

Насколько я помню, внешний ключ должен относиться к уникальной сущности. В вашем случае вам нужно реализовать всю логику в триггерах BEFORE вместо использования внешних ключей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...