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

Предположим, у меня есть таблица со следующими атрибутами

  • номер заказа
  • идентификатор товара
  • количество товара
  • цена единицы товара
  • пункт оплаты

где "оплата товара = цена за единицу товара x количество товара". Давайте упростим ситуацию и предположим, что каждый заказ имеет любое количество только одного идентификатора товара, а разные заказы могут иметь один и тот же идентификатор товара.

  1. Что такое первичный ключ, "идентификатор заказа", "идентификатор заказа" и "идентификатор товара", или что-то еще?
  2. Как это можно нормализовать в 3NF?

    Вот решение, которое я думаю:

    • таблица с идентификатором заказа (первичный ключ), идентификатором товара, количеством товара и оплатой товара

    • таблица с идентификатором товара (первичный ключ и внешний ключ к предыдущей таблице) и ценой за единицу товара.

  3. Продолжайте с предварительным решением, которое я дал в части 2. В первой таблице для каждого идентификатора изделия оплата товара пропорциональна количеству товара. Если первичным ключом первой таблицы является идентификатор заказа, оплата товара зависит от количества товара атрибута, не являющегося первичным ключом, что нарушает требования 3NF об отсутствии транзитивности.

    Должен ли я разделить первый стол на:

    • таблица с идентификатором заказа (первичный ключ) и идентификатором товара
    • таблица с идентификатором товара (первичный ключ и внешний ключ к предыдущей таблице), количеством товара и оплатой товара

    или в:

    • таблица с идентификатором заказа (первичный ключ) и идентификатором товара
    • таблица с ценой единицы товара (первичный ключ и внешний ключ к исходной второй таблице), количеством товара и оплатой товара?

Благодарю.

4 ответа

Вероятно, у вас должна быть таблица с OrderID в качестве первичного ключа. Это связано с тем, что у вас, скорее всего, есть атрибуты с нетривиальными функциональными зависимостями в заказе (например, order_date, order_status, CustomerID), которые не зависят от строки в заказе.

Вы также должны снова иметь таблицу, где ItemID является первичным ключом. Опять же, он будет иметь атрибуты, которые будут иметь функциональные зависимости от ItemID (например, описание, цена и т. Д.)

Наконец, у вас будет третий стол. Эта таблица будет иметь внешние ключи для Order и Item. Эти ключи будут представлять собой составной ключ-кандидат. Вы можете использовать это или создать суррогатный первичный ключ OrderItemID. Если вы создадите суррогатный ключ, я все равно обязательно создам уникальный ключ (OrderID, Item).

     +----------------+         +----------------+
     |  OrderID       |         |    ItemID      |
     +----------------+         +----------------+
     |  CustomerID    |         |   Description  |
     |  OrderDate     |         |   Price        |
     |  Status        |         +----------------+
     |  Payment       |                       |
     +----------------+                       |
            |                                 |
            |                                 |
            |       +---------------------+   |
            |       |   OrderItemID       |   |
            |       +---------------------+   |
            +-------+   OrderID  FK U1    +---+
                    |   ItemID   FK U1    |
                    |   Quantity          |
                    +---------------------+

Давайте не будем говорить об идентификаторах в начале...

  1. Есть заказы. У заказов обычно есть номер заказа, который вы можете напечатать в счете-фактуре и т. Д. В заказе есть дата заказа и поставщик, когда речь идет о заказах, которые вы размещаете у своих поставщиков или у клиента, когда речь идет о заказах, которые ваши клиенты размещают у вас.
  2. Есть предметы, которые можно заказать. Предметы имеют номер предмета, например, GTN (глобальный торговый номер). Товары имеют название и цену или даже прайс-лист на разные даты, разных клиентов, что угодно.
  3. Заказ обычно может содержать несколько товаров, например, 5 штук товара A и 10 штук товара B. Это позиции заказа, содержащие товар, количество и цену.

Это могут быть таблицы (жирный шрифт первичного ключа, курсив уникальных столбцов):

  • клиент (номер_клиента, имя_клиента)
  • вещь (номертовара, имя товара, цена)
  • заказ (порядковый номер, порядковый номер, клиентский номер)
  • позиция заказа (номерзаказа, номер товара, сумма, цена)

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

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

Таблицы (жирный шрифт первичного ключа, курсив уникальных столбцов):

  • client (client_id, client_number, client_name)
  • item (item_id, item_number, item_name, цена)
  • order (order_id, order_number, order_date, client_number)
  • order_position (order_position_id, order_id + item_id, сумма, цена)

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

Оплата суммы по строке заказа - это нормально, если вы разрешаете частичные платежи и хотите отслеживать их на этом уровне.

Догадываясь через ваши имена и здравый смысл, 3NF декомпозиция вашей таблицы

-- order order_id requests item item_id in quantity item_quantity
order_has_item_in_quantity(order_id, item_id, item_quantity)

-- item item_id has unit price item_unit_price
item_has_unit_price(item_id, item_unit_price)

--     some order requests some item in quantity item_quantity
-- and that item has unit price item_unit_price
-- and item_unit_price * item_quantity = item_payment
unit_price_and_quantity_has_payment(item_unit_price, item_quantity, item_payment)

Однако, если у вас уже есть доступ к таблице умножения (которая является константой), что вы делаете в запросе SQL (через оператор *), тогда ваш дизайн не нуждается в колонке item_payment в оригинале и, следовательно, его разложение не имеет таблицы unit_price_and_quantity_has_payment- это определенное ограничение таблицы умножения; это определенная функция таблицы умножения и первых двух таблиц.

Что касается моих догадок, соответствующих CK (ключей-кандидатов) и обоснования: нормализация использует FD (функциональные зависимости), и вы их не упомянули, поэтому, похоже, у вас нет даже базового представления о том, что вы делаете, Итак, прямо сейчас ваш вопрос состоит в том, чтобы попросить некоторые главы некоторых учебников. Это слишком широко - читайте некоторые. Ни один из ответов здесь правильно не объясняет и не ссылается на то, как это сделать - они бесполезны для следующего случая и неоправданны для этого случая. Более того, все они предполагают, что у вас есть спецификации, но должны спрашивать у вас соответствующую информацию.

Другие вопросы по тегам