Apenas olhando para sapatos, você tem uma entidade:sapatos. Possui dois atributos diretos:tamanho e cor. O domínio de cada um desses atributos deve ser estritamente definido, o que indica tabelas de consulta para eles. Existem dois atributos indiretos, preço e quantidade, mas esses são atributos mais de cada combinação de tamanho/cor do que de um sapato em si.
Isso sugere uma tabela de entidades:Shoes; duas tabelas de consulta:Tamanhos e Cores; e uma tabela de interseção de três vias:ShoeStyles:
create table ShoeStyles(
ShoeID int not null,
SizeID smallint not null,
ColorID char( 1 ) not null,
Price currency,
Qty int not null default 0,
constraint FK_ShoeStyles_Shoe foreign key references Shoes( ID ),
constraint FK_ShoeStyles_Size foreign key references Sizes( ID ),
constraint FK_ShoeStyles_Color foreign key references Colors( ID ),
constraint PK_ShoeStyles primary key( ShoeID, SizeID, ColorID )
);
Assim, por exemplo, a combinação ('Penny Loafer', '10 1/2', 'Tan') terá um determinado preço e quantidade disponível. O tamanho 11 Tan terá seu próprio preço e quantidade, assim como o 10 1/2 Borgonha.
Eu recomendaria uma visão que una as tabelas e apresente os resultados de uma forma mais útil, como mostrado acima, em vez de, digamos, (15, 4, 3, 45,00, 175). Os acionadores na exibição podem permitir todo o acesso do aplicativo por meio da exibição para que o aplicativo permaneça independente do layout físico dos dados. Essas visualizações são uma ferramenta extremamente poderosa que aumenta significativamente a robustez e a capacidade de manutenção dos dados subjacentes e do próprio aplicativo, mas que são lamentavelmente subutilizados.