Хранение цены в таблице 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.