Ограничения внешнего ключа полиморфной ассоциации. Это хорошее решение? - PullRequest
13 голосов
/ 30 октября 2011

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

Тем не менее, я сделал многоисследование по этому вопросу.Я знаю минусы использования полиморфных ассоциаций и минусы.Но я нашел то, что кажется достойным решением:

http://blog.metaminded.com/2010/11/25/stable-polymorphic-foreign-key-relations-in-rails-with-postgresql/

Это хорошо, потому что вы получаете лучшее из обоих миров.Меня беспокоит дублирование данных.У меня недостаточно глубоких знаний о postgresql, чтобы полностью понять стоимость этого решения.

Что вы думаете?Следует ли полностью избегать этого решения?Или это хорошее решение?

Единственной альтернативой, на мой взгляд, является создание внешнего ключа для каждого типа ассоциации.Но затем вы сталкиваетесь с тем, что существует только одна ассоциация.Это ситуация «выбери свой яд».Полиморфные ассоциации четко описывают намерение, а также делают этот сценарий невозможным.На мой взгляд, это самое главное.Ограничение внешнего ключа базы данных является закулисной функцией, и изменение «намерения» работать с ограничениями базы данных кажется мне неправильным.Вот почему я хотел бы использовать вышеупомянутое решение, предполагая, что с ним нет явного «избегания».

Ответы [ 2 ]

10 голосов
/ 31 октября 2011

Самая большая проблема, с которой я столкнулся при реализации INHERITS в PostgreSQL, заключается в том, что вы не можете установить ссылку на внешний ключ для родительской таблицы. Есть много случаев, когда вам нужно это сделать. Смотрите примеры в конце моего ответа.

Решением является создание таблиц, представлений или триггеров вне Rails. Как только вы решите это сделать, я думаю, вы могли бы также использовать самую лучшую структуру, какую только сможете найти.

Я давно использовал базовую родительскую таблицу, применяя непересекающиеся подтипы с использованием внешних ключей. Эта структура гарантирует, что может существовать только одна ассоциация, и что эта ассоциация разрешается в правильный подтип в родительской таблице. (В слайд-шоу Билла Карвина по антипаттернам SQL этот подход начинается на слайде 46.) В простых случаях это не требует триггеров, но я обычно предоставляю одно обновляемое представление для каждого подтипа и требует использования клиентского кода Виды. В PostgreSQL обновляемые представления требуют написания триггеров или правил. (Версии до 9.1 требуют правил.)

В самом общем случае непересекающиеся подтипы не имеют одинакового числа или вида атрибутов. Вот почему мне нравятся обновляемые представления.

Наследование таблиц не переносимо, но такая структура есть. Вы даже можете реализовать это в MySQL. В MySQL необходимо заменить ограничения CHECK ссылками на внешние ключи для однострочных таблиц. (MySQL анализирует и игнорирует ограничения CHECK.)

Не думаю, что вам нужно беспокоиться о дублировании данных. Во-первых, я уверен, что данные не дублируются между родительскими таблицами и наследующими таблицами. Просто так кажется. Во-вторых, дублирование или производных данных, целостность которых полностью контролируется БД, не является особенно горькой пилюлей для проглатывания. (Но неконтролируемое дублирование есть.)

Подумайте, должен ли удаляться каскад.

3 голосов
/ 30 октября 2011

Вы не можете применить это в базе данных простым способом - так что это действительно плохая идея.Лучшее решение обычно простое - забудьте о полиморфных ассоциациях - это вкус антипаттерна.

...