Ограничения внешнего ключа в полиморфной ассоциации. Это хорошее решение?

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

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

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

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

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

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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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