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

StackOverflow https://stackoverflow.com/questions/448592

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top