Exemplo simples: existe uma tabela de clientes.
create table Customers (
id integer,
constraint CustomersPK primary key (id)
)
Todos os outros dados no banco de dados devem estar vinculados a um Customer
, então, por exemplo, Orders
fica assim:
create table Orders (
id integer,
customer integer,
constraint OrdersPK primary key (customer, id),
constraint OrdersFKCustomers foreign key (customer) references Customers (id)
)
Suponha que agora exista uma tabela com links para 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)
)
Devo adicionar uma chave estrangeira separada de Items
para Customers
?
...
constraint ItemsFKCustomers foreign key (customer) references Customers (id)
Uma imagem: devo adicionar a linha tracejada / FK?
Editar: adicionei definições de chave primária às tabelas. Gostaria de reiterar o que afirmei acima: o banco de dados é basicamente isolado pelos clientes, como uma medida de correção / segurança. Portanto, todas as chaves primárias contêm o customer
ID.
database-design
foreign-key
vektor
fonte
fonte
Respostas:
Eu acho que essa é a ideia original.
A primeira coisa a notar é que a PK na tabela LineItem possui três atributos
{CustomerID, CustomerOrderNo, OdrerItemNo}
, em vez de apenas dois no seu exemplo.A segunda coisa a observar é a confusão resultante do uso do
id
nome genérico para um atributo.O
CustomerOrderNo
deve ser idealmente (1,2,3 ..) para cada cliente eOrderItemNo
(1,2,3 ...) para cada ordem.Bem, isso é bom, se possível, mas requer uma consulta procurando o valor máximo anterior, como
que geralmente não é preferido em ambientes de alto volume de transações, por isso é comum vê-los substituídos por um incremento automático, essencialmente servindo ao mesmo objetivo. É verdade que esse incremet automático agora é exclusivo, portanto, pode ser usado como uma CHAVE - mas você pode optar por considerá-lo como um compromisso necessário para o
OrderItemNo
.Então, com algumas renomeações
CustomerOrderNo -> OrderNo
eOrderItemNo
->ItemNo
você pode chegar a esse modeloEntão agora, se você olhar para
Order
o seguinte, é únicoObserve que
{CustomerID, OrderNo}
é propagado para oLineItem
para servir como um FK.Se você apertar os olhos um pouco, isso é parecido com o seu exemplo, mas com
PKs {ItemNo} and {OrderNo}
apenas - em oposição a duas PKs de coluna do seu exemplo.Agora, a pergunta é: por que não simplificar para algo assim?
Que é bom, mas introduz PATH DEPENDÊNCIA - você não pode juntar-se
LineItem
comCustomer
diretamente, deve usarOrder
na junção.Prefiro o primeiro caso, quando possível - você escolhe o seu favorito. E, obviamente, não há necessidade de FK direto de
LineItem
paraCustomer
nesses três casos.fonte
O "item" não deve fazer referência direta ao "cliente", porque isso está implícito no "pedido" do item. Portanto, você não precisará das colunas "customer" na tabela "items".
A relação do item com o cliente é garantida com a chave estrangeira existente.
Se orders.id for uma coluna de identidade, considere remover items.customer no total.
fonte
customer
em todas as tabelas (e assim silenciar o DB) é uma abordagem incomum. Devo confessar que é apenas algo que vi no meu trabalho anterior. Isso faz algum sentido para você? Você já viu esse design antes?