Как предотвратить потерянные записи в подробных таблицах нормализованной базы данных?

Я должен поддерживать старую базу данных, которая не нормализована должным образом. Например, есть таблица проекта, которая выросла (или, может быть, выросла), чтобы иметь 5 или более различных столбцов даты, для разных этапов проекта от заказа до даты поставки. Есть также несколько таблиц, каждая из которых содержит столбцы для уличных адресов, почтовых адресов или веб-ссылок.

Я хотел бы нормализовать структуру, создать таблицы для адресов, запланированных дат и т. П., А также необходимые таблицы для учета отношений 1:N (адрес на клиента, срок выполнения для проекта и т. Д.).

Прямо сейчас я совершенно не уверен, как обрабатывать изменения данных в таблицах подробностей. Рассмотрим, например, изменение адреса доставки клиента. Об изменении данных в таблице адресов не может быть и речи, поскольку более одной записи (возможно, в более чем одной таблице) может ссылаться на эту запись. Добавление новой записи адреса может оставить старую запись потерянной, если ни одна другая строка не имеет отношения к нему по внешнему ключу.

Я думал о следующих способах справиться с этим:

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

  • Пусть триггер попытается удалить старую детальную запись и поймать любые ошибки. Это просто неправильно.

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

Каков предпочтительный способ обработки изменений данных в таблицах подробностей, которые связаны с несколькими основными таблицами? Любые советы для чтения по этому вопросу?

3 ответа

Решение

Частично проблема может заключаться в оригинальном дизайне схемы: внешние ключи указывают неверный путь, обрабатывая адреса, номера телефонов и т. Д. Как главные, а не детали. Это может быть удобно, когда вы хотите, чтобы все варианты использования определенного адреса обновлялись одновременно, но, по моему опыту, это всегда превращается в слишком много сложных исключительных случаев, например, один человек в каком-либо месте перемещается, поэтому вам нужно разорвать их связь с целым переезд в дом или офис, чтобы вы обновили существующую запись. Если вы попытаетесь скрыть эту деталь от пользователя на экране CRUD, вы окажетесь в ситуации, когда он просто не будет делать то, что вы хотите.

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

Если вы хотите, например, несколько адресов для каждого контакта, сделайте адреса подробной таблицей с внешним ключом, указывающим на родительский контакт, и не беспокойтесь о дублированных значениях адресов, потому что они просто значения. В противном случае, сделайте Address реальной сущностью: добавьте поле заголовка или описания и экран CRUD, чтобы он мог стоять как сущность.

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

Я думаю, что вы стираете случаи удаления и обновления.

Если у вас есть клиент a и клиент b, и оба используют один и тот же адрес, который будет отражен в записях в реляционной таблице (скажем, ClientAddresses, хотя, если вы храните адреса для нескольких объектов, я уверен, что это будет более сложным, чем тот)

Я думаю, что если два клиента совместно используют и адресуют, и это неверно для клиента a, это будет некорректно и для клиента b (т. Е. Ошибка ввода данных), но если вы уверены, что не хотите, чтобы клиент вносил изменения в сделанные информацию о базовом адресе, удалите запись ассоциации (удалить из ClientAddresses) и добавьте новый адрес. Когда вы выполняете удаление из реляционной таблицы (предположительно из хранимой процедуры), проверьте, есть ли какие-либо другие записи, относящиеся к диссоциированной записи адреса, если не удалить из базовой таблицы.

Другие вопросы по тегам