В старой кодовой базе появилось новое требование, которое в основном обеспечивает прямую (внутреннюю) связь между двумя ранее не связанными напрямую классами пользователей (хранящимися в разных таблицах с совершенно другой схемой, и, к сожалению, код практически не поддерживает ОО, очень менее разработанный, так что нет родительского класса). Поскольку мы стремимся повесить сумку на эту старую установку, которая никогда не учитывала эту функциональность, нет гарантии, что не будет коллизий PK - учитывая используемый набор данных, практически гарантировано, что есть.
Таким образом, решение кажется очевидным: убить его с помощью огня и переписать всю таблицу ошибок. Я получил два направления для возможных способов реализации карты, но я не администратор баз данных, поэтому я не уверен, есть ли какие-то плюсы и минусы, которые я пропустил.
Для пояснения абстракции рассмотрим три группы разнородных пользовательских данных: профессора, администрация, студенты (нет, это не домашнее задание. Обещание!)
Картирование 1
(Professor_id, admin_id и student_id являются внешними ключами для соответствующих таблиц)
| mailing_id (KEY) | professor_id | admin_id | student_id |
-------------------------------------------------------
| 1001 | NULL | 87 | NULL |
| 1002 | 123 | NULL | NULL |
| 1003 | NULL | NULL | 123 |
+/- к этому подходу кажется довольно тяжелым минусы:
- Два «впустую» поля в строке
- Нарушает 2НФ
- Уязвим для вставки / обновления аномалий (например, строка с полем 0-1, установленным NULL, например)
Плюсы не лишены своих достоинств, хотя:
- Отображение может быть выполнено с помощью одного поиска
- Легко определить «исходные» данные для данного пользователя из mailing_id
По правде говоря, мне не нравится эта идея.
Картографирование 2
(предположим, что MSG_ * - это определенные константы, типы перечислений или другой подходящий идентификатор)
| mailing_id (KEY) | user_type (UNIQUE1) | internal_id (UNIQUE2)|
------------------------------------------------------------------
| 1001 | MSG_ADMIN | 87 |
| 1002 | MSG_PROF | 123 |
| 1003 | MSG_STUDENT | 123 |
С этой настройкой и уникальным составным индексом {user_type, internal_id} все становится намного чище, поддерживается 3NF, и код приложения не должен проверять аномалии ввода / вывода.
С другой стороны, существует некоторая потеря прозрачности при определении пользовательских таблиц-источников, которые должны обрабатываться за пределами БД, что в основном сводится к сопоставлению значений user_type с таблицами на уровне приложения. Прямо сейчас я (довольно сильно) склоняюсь к этому 2-му отображению, так как недостаток довольно незначительный.
НО я до боли осознаю свои собственные ограничения, и я уверен, что я, вероятно, упустил преимущества или камни преткновения в обоих направлениях, поэтому я обращаюсь к более разумным умам, чем мой.
источник
Ответы:
Твоя вторая идея верна. Этот подход позволяет вам сделать все сопоставления, которые вам нужно сделать, чтобы интегрировать три ваших сталкивающихся ключевых пространства.
Важно отметить, что это позволяет базе данных навязывать большую часть согласованности, которая вам необходима при использовании декларативных ограничений .
У вас уже есть больше кода, чем вы хотели бы иметь, поэтому не добавляйте больше кода, чем это абсолютно необходимо для поддержания согласованности вашего интегрированного списка ключей. Позвольте вашей базе данных делать то, для чего она была создана.
«Проблемный ребенок», вызывающий дискомфорт в Mapping 2, - это
USER_TYPE
столбец. Этот столбец важен, поскольку он необходим для того, чтобы онINTERNAL_ID
отображался не более одного раза для каждого типа пользователя. Единственный раз, когда вам нужен какой-либо код, о котором даже известно,USER_TYPE
это код, который вставляется и удаляется из вашей таблицы сопоставления. Это может быть локализовано довольно хорошо. Я бы предположил, что вы создадите единственную точку в вашем коде, где поддерживается содержимое таблицы сопоставления. Дополнительный столбец в этом месте, где записываются данные , не имеет большого значения. Чего вы действительно хотите избежать, так это добавлять дополнительный столбец везде, где читаются данные .Код в ваших подприложениях, который должен использовать отображение, может блаженно не знать
USER_TYPE
просто, предоставляя каждому подприложению представление, которое фильтрует отображения к одному типу пользователя конкретного приложения.источник
Исходя из своего опыта, я рекомендую выбирать последовательность, а не элегантность или «лучшие практики». Это должно соответствовать существующему дизайну и использовать ТРИ почтовые таблицы (по одной для каждой роли) с простой
mailing_id, user_id
структурой полей.Это не элегантно, но имеет несколько преимуществ ...
Я уверен, что многие другие не согласятся с этим подходом, но основные цели нормализации и передовой практики - сделать код более согласованным, чтобы его было проще отслеживать и отлаживать ... и, очевидно, доведение всей базы кода до нуля, вероятно, неосуществимо.
источник