Является ли это хорошим способом моделирования адресной информации в реляционной базе данных?

Мне интересно, хороший ли это дизайн. У меня есть несколько таблиц, которые требуют адресной информации (например, улица, почтовый индекс/почтовый индекс, страна, факс, электронная почта). Иногда один и тот же адрес повторяется несколько раз. Например, адрес может храниться у поставщика, а затем по каждому заказу на поставку, отправленному им. Затем поставщик может изменить свой адрес, и любые последующие заказы на поставку должны иметь новый адрес. Это сложнее, чем это, но это примерное требование.

Вариант 1 Поместите все столбцы адресов в качестве атрибутов в различные таблицы. Скопируйте детали вниз от поставщика к ПО по мере его создания. Потенциально хранить несколько копий

Вариант 2 Создайте отдельную таблицу адресов. Имейте внешний ключ от поставщика и таблицы заказов на поставку в адресную таблицу. Только разрешить вставку и удаление в таблице адресов, поскольку обновления могут измениться больше, чем вы планируете. Тогда у меня будет какая-то запланированная задача, которая удалит любые строки из таблицы адресов, на которые больше не ссылаются ни на что, так что неиспользуемые строки не остались. Возможно, также есть уникальное ограничение для всех столбцов non-pk в таблице адресов, чтобы остановить дубликаты.

Я склоняюсь к варианту 2. Есть ли лучший способ?

EDIT: я должен сохранить адрес в заказе на поставку, как это было при отправке. Кроме того, это немного сложнее, чем я предложил, поскольку там могут быть адрес доставки и адрес выставления счетов (там также есть множество других таблиц, которые имеют адресную информацию).

Через некоторое время я удалю старые заказы на поставку в соответствии с их датой. Именно после этого я собирался на мусор, собирающий любые записи адресов, которые больше не ссылаются ни на что (в противном случае я чувствую, что создаю утечку).

Ответ 1

Я действительно использую это как один из моих интервью. Для начала нужно начать следующее:

Addresses
---------
AddressId (PK)
Street1
... (etc)

и

AddressTypes
------------
AddressTypeId
AddressTypeName

и

UserAddresses (substitute "Company", "Account", whatever for Users)
-------------
UserId
AddressTypeId
AddressId

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

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

Ответ 2

Вариант 2, без сомнения.

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

Также; Я настоятельно рекомендую хранить старые данные адреса; не запускайте процесс очистки. Если у вас нет загруженной базы данных, ваше программное обеспечение базы данных сможет обрабатывать избыточные данные. В самом деле. Одна распространенная ошибка, которую я вижу о базах данных, пытается переоценить; вы хотите оптимизировать ад из своих запросов, но вы НЕ хотите оптимизировать свои неиспользуемые данные. (Опять же, если ваша активность в базе данных ОЧЕНЬ ВЫСОКАЯ, вам может потребоваться что-то сделать, но это почти уверенность в том, что ваша база данных будет работать хорошо, все еще имея избыточные данные в таблицах.) В большинстве ситуаций это на самом деле более выгодно просто позволить вашей базе данных расти, чем пытаться ее оптимизировать. (Исключение спорадических данных из ваших таблиц не приведет к значительному уменьшению размера вашей базы данных, и когда это произойдет... ну, переиндексирование, которое вызывает, может быть гигантским утечкой в ​​базе данных.)

Ответ 3

Думаю, я согласен с JohnFx..

Другое дело о (уличных) почтовых адресах, так как вы хотите включить страну, я предполагаю, что вы хотите отправлять/отправлять по всему миру, пожалуйста, держите поле адреса главным образом в формате свободной формы. Это очень неприятно, когда приходится составлять 5-значный почтовый индекс, если в Норвегии нет почтовых индексов, у нас есть 4-значный почтовый индекс.

Лучшие поля:

  • имя/Название компании
  • Адрес (многострочная текстовая область)
  • Страна

Это должно быть довольно глобальным, если почтовая система в США требует почтовых кодов в определенном формате, тогда включите это тоже, но сделайте это необязательным, если только США не будут выбраны в качестве страны. Каждый знает, как отформатировать адрес в своей стране, так что, пока вы держите линии, это должно быть хорошо...

Ответ 4

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

Если да, пойдите с опцией 1, в противном случае сохраните ее в таблице поставщика и свяжите каждый заказ на поставку с поставщиком.

BTW: верным признаком плохой конструкции БД является необходимость автоматического задания для "очистки" данных или синхронизации. Вариант 2, вероятно, является плохим результатом этой меры

Ответ 5

Почему какая-либо из строк в таблице адресов не используется? Наверняка они все равно будут указывать на заказ на покупку, который их использовал?

Мне кажется, что остановка дубликатов должна быть приоритетом, что отрицает необходимость какой-либо очистки.

Ответ 6

В случае заказов вы никогда не захотите обновлять адрес, если адрес человека (или компании) изменился, если заказ был отправлен. Вы нашли запись о том, где заказ был отправлен, если есть проблема с заказом.

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

Ответ 7

Я видел, как каждая система, использующая параметр 1, попадает в проблему с качеством данных. Через 5 лет 30% всех адресов перестанут быть актуальными.