Как предотвратить потерянные записи в подробных таблицах нормализованной базы данных? - PullRequest
1 голос
/ 16 января 2009

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

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

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

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

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 16 января 2009

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

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

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

3 голосов
/ 16 января 2009

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

0 голосов
/ 16 января 2009

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

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

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

...