Простой пример: есть таблица клиентов.
create table Customers (
id integer,
constraint CustomersPK primary key (id)
)
Все остальные данные в базе данных должны быть связаны с Customer
, например, Orders
так:
create table Orders (
id integer,
customer integer,
constraint OrdersPK primary key (customer, id),
constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Предположим, теперь есть таблица, ссылающаяся на Orders
:
create table Items (
id integer,
customer integer,
order integer,
constraint ItemsPK primary key (customer, id),
constraint ItemsFKOrders foreign key (customer, order) references Orders (customer, id)
)
Должен ли я добавить отдельный внешний ключ от Items
к Customers
?
...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Картина вместо этого: я должен добавить пунктирную линию / FK?
Изменить: я добавил определения первичного ключа в таблицы. Я хотел бы еще раз повторить сказанное мной выше: база данных в основном отбирается клиентами в качестве меры корректности / безопасности. Поэтому все первичные ключи содержат customer
идентификатор.
database-design
foreign-key
Vektor
источник
источник
Ответы:
Я думаю, что это оригинальная идея.
Первое, на что нужно обратить внимание, это то, что PK в таблице LineItem имеет три атрибута
{CustomerID, CustomerOrderNo, OdrerItemNo}
, а не два в вашем примере.Второе, на что следует обратить внимание, - это путаница, возникшая из-за использования общего
id
имени для атрибута.В
CustomerOrderNo
идеале должно быть (1,2,3 ..) для каждого клиента иOrderItemNo
(1,2,3 ...) для каждого заказа.Ну, это хорошо, если это возможно, но требует, чтобы запрос искал предыдущее максимальное значение, например
что часто не является предпочтительным в средах с большим объемом транзакций, поэтому обычно их заменяют на автоинкремент, по существу служащий той же цели. Это правда, что этот автоинкремент теперь уникален, поэтому его можно использовать как КЛЮЧ - но вы можете рассмотреть его как необходимый компромисс для
OrderItemNo
.Итак, с некоторым переименованием
CustomerOrderNo -> OrderNo
иOrderItemNo
->ItemNo
вы можете прийти к этой моделиТак что теперь, если вы посмотрите на
Order
следующие уникальныеОбратите внимание, что
{CustomerID, OrderNo}
распространяется наLineItem
в качестве FK.Если вы немного покоситесь, это близко к вашему примеру, но
PKs {ItemNo} and {OrderNo}
только - в отличие от двух колонок PK из вашего примера.Теперь вопрос, почему бы не упростить что-то подобное?
Что хорошо, но вводит PATH ЗАВИСИМОСТЬ - вы не можете присоединиться
LineItem
сCustomer
непосредственно, должны использоватьOrder
в соединении.Я предпочитаю первый случай, когда это возможно - вы выбираете свой любимый. И, очевидно, в этих трех случаях нет необходимости в прямом ФК от
LineItem
доCustomer
.источник
«Товар» не должен напрямую ссылаться на «клиента», потому что это подразумевается «заказом» товара. Таким образом, вам не понадобятся столбцы "customer" в таблице "items".
Отношение товара к покупателю обеспечивается существующим внешним ключом.
Если orders.id является столбцом идентификаторов, рассмотрите возможность полного удаления items.customer.
источник
customer
во всех таблицах (и, следовательно, бункера БД) является необычным подходом. Я должен признаться, что это просто то, что я видел в моей предыдущей работе. Это имеет какой-то смысл для вас? Вы видели такой дизайн раньше?