Как обращаться с неизменяемой таблицей, ссылающейся на изменяемые таблицы? - PullRequest
2 голосов
/ 23 августа 2009

Создавая довольно стандартный интернет-магазин в .NET, я столкнулся с небольшой архитектурной загадкой, касающейся моей базы данных. У меня есть таблица «Заказы», ​​на которую ссылается таблица «OrderItems». Последний ссылается на таблицу «Продукты».
Теперь таблицы заказов и элементов заказа в большинстве аспектов неизменны, то есть созданный заказ и его элементы заказа должны выглядеть одинаково, независимо от того, смотрите ли вы на таблицы (например, печатать квитанцию ​​на заказ для учета каждый год) должен выдать ту же квитанцию, которую клиент получил во время заказа).
Я могу думать о двух способах достижения этого поведения, один из которых используется сегодня:
1. Денормализация, когда такие значения, как цена продукта, копируются в таблицу элементов заказа.
2. Сделать ссылочные таблицы неизменяемыми. Код, который обрабатывает продукты, может создавать новый продукт всякий раз, когда изменяется такое значение, как цена. Изменяемые таблицы, ссылающиеся на продукты, могут обновлять ссылки, тогда как неизменяемые таблицы будут хорошими и модными со своей старой ссылкой

.

Какой ваш предпочтительный способ сделать это? Есть ли лучший, более умный способ сделать это?

Ответы [ 3 ]

4 голосов
/ 24 августа 2009

Это зависит. Я пишу о довольно сложном корпоративном программном обеспечении, которое включает в себя управление документами и аудит и используется в аптеке.

Обычно примитивные значения денормализованы. Например, если вам просто нужно текущее состояние клиента при создании заказа, я бы сохранил его в заказе.

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

История означает, что каждое когда-либо существовавшее состояние сохраняется как отдельная запись в той же или другой таблице.

Я внедрил систему контроля версий, в которой я делю записи на две таблицы: одну для реального элемента, скажем, для продукта, а другую для его версий. Таким образом, я могу ссылаться на продукт в целом или на любую его конкретную версию, поскольку оба имеют свой собственный первичный ключ.

Эта система используется для многих организаций. Я могу смело ссылаться на объект под контролем ревизии, например, из контрольного журнала или других неизменяемых записей. Поначалу кажется, что иметь такую ​​систему сложнее, но в конце она очень прямолинейна и решает сразу много проблем.

1 голос
/ 24 августа 2009

Хранение цены в таблице Product и таблице OrderItem НЕ денормализуется, если цена может меняться со временем. Правила нормализации говорят, что каждый «факт» должен быть записан в базу данных только один раз. Но в этом случае, просто потому, что оба числа называются «цена», не делает их одно и то же. Одним из них является текущая цена, другим является цена на дату продажи. Это очень разные вещи. Также как «почтовый индекс покупателя» и «почтовый индекс магазина» - это совершенно разные поля; тот факт, что оба могут быть названы «почтовый индекс» для краткости, не делает их одно и то же. Лично у меня есть сильное отвращение к тому, чтобы поля, содержащие разные данные, имели одинаковые имена, потому что это создает путаницу. Я бы не назвал их обоих «Цена»: я бы назвал одну «Current_Price», а другую «Sale_Price» или что-то в этом роде.

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

Дублирование всей записи о продукте для каждой продажи или каждый раз, когда цена меняется, также неверно. У вас почти наверняка есть постоянные данные о продукте, такие как описание и поставщик, которые не меняются каждый раз, когда меняется цена. Если вы продублируете запись о продукте, вы продублируете все эти данные, что, безусловно, является денормализацией. Это создает много потенциальных проблем. Например, если кто-то исправит орфографическую ошибку в описании продукта, у нас может появиться новая запись «Тостер с 4 ломтиками», в то время как старая запись говорит «Дегустатор с 4 ломтиками». Если мы создадим отчет и отсортируем описание, они будут разделены и будут выглядеть как разные продукты. И т.д.

Если единственные данные, которые меняют информацию о товаре и которые вас интересуют, это цена, то я просто опубликую цену в записи OrderItem.

Если есть много данных, которые изменяются, то вы хотите разбить таблицу Product на две таблицы: одну для данных, которые являются постоянными или чья история вам не нужна, и другую для данных, где вам нужно отслеживать история. Например, иметь таблицу ProductBase с описанием, поставщиком, номером склада, весом при транспортировке и т. Д .; и таблица ProductMutable с нашей себестоимостью, продажной ценой и всем остальным, что постоянно меняется. Вы, вероятно, также хотите получить дату или, по крайней мере, указание на текущую дату. Первичным ключом ProductMutable может быть Product_id плюс As_of_date или, если вы предпочитаете простые последовательные ключи для всех таблиц, хорошо, по крайней мере, он имеет ссылку на product_id. Таблица OrderItem ссылается на ProductMutable, а не на ProductBase. Мы находим ProductBase через ProductMutable.

0 голосов
/ 24 августа 2009

Я думаю, что денормализация - это путь.

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

Вы также можете иметь таблицу истории цен, в которой она содержит ProductID, FromDate, ToDate, Price, IsActive - для ведения истории цен для продукта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...