Pergunta

Ok, então eu estou fazendo uma mesa agora para "Caixa de itens".

Agora, uma caixa Item, dependendo do que ele está sendo usado para a / o status do item, pode acabar sendo relacionado a uma caixa de "envio" ou uma caixa de "Volta".

A caixa item pode estar com defeito: se for, uma bandeira será definido na linha de caixa Item (IsDefective), ea Caixa artigo será colocado em uma caixa "Returns" (com outros itens a serem devolvidos para que fornecedor). Caso contrário, o Box item acabará por ser colocado em uma caixa de "envio" (com outros itens a serem enviados). (Note-se que transporte e retorna caixas têm os seus próprios quadros: não há uma mesa comum para todas as caixas ... embora talvez eu deva considerar fazer que, se possível, como uma terceira possibilidade)

Talvez eu só não estou pensando claramente hoje, mas eu comecei a questionar o que deve ser feito nesta situação.

Meu instinto me diz que eu deveria ter um campo separado para cada relação possível, mesmo que apenas uma das relações podem acontecer a qualquer momento, o que tornaria o esquema para Caixa Itens parecido:

BoxItemID Descrição Está com defeito ShippingBoxID ReturnBoxID etc ...

Isto faria com que as relações claras, mas parece um desperdício (uma vez que apenas uma das relações vai ser usado a qualquer momento). Então eu pensei que eu poderia ter apenas um campo para o BoxID, e determinar quais BoxID ele está se referindo a (a envio ou a Volta Box ID) com base no campo IsDefective:

BoxItemID Descrição Está com defeito BoxID etc ...

Isto parece menos desperdício, mas não se sente bem comigo. A relação não é óbvia.

Então, eu colocá-lo para você, gurus de banco de dados de Stackoverflow. O que você faria nessa situação?

EDIT: Obrigado a todos por sua entrada! Ele me deu um monte de pensar. Por um lado, eu vou usar um ORM próxima vez que eu começar um projeto como este. =) Para dois, desde que eu não sou agora, eu vou morder os quatro bytes e usar dois campos.

Obrigado a todos novamente!

Foi útil?

Solução

Eu estou com Psychotic Venom e mattlant.

Indo a rota polimórficos (ter que descobrir qual tabela os seus pontos chave estrangeira para com base no conteúdo de outro campo) vai ser uma dor. Codificar as restrições para que talvez difícil (não estou certo que a maioria bancos de dados apoiaria que nativamente, eu acho que você tem que usar um gatilho).

itens sempre mover entre as mesas? Cumprindo com duas tabelas com definições idênticas onde um é para retornos e um é para o transporte pode ser o caminho mais fácil. Se você quiser ficar com a definição que você propôs pela primeira vez (com os dois campos separados) é perfeitamente razoável.

"otimização prematura é a raiz de todo o mal" e tudo isso. Enquanto isso parece um desperdício, lembre-se que você está armazenando. Uma vez que são IDs eles são provavelmente apenas números inteiros, talvez 4 bytes. Desperdiçando quatro bytes por registro é basicamente nada. Na verdade, devido ao preenchimento de colocar as coisas em endereços mesmo ou outras coisas que podem ser "livre" para colocar esse campo extra lá. Tudo depende do projeto DB.

A menos que você tenha uma boa razão para ir a rota polimórficos (como se estivesse em um sistema embarcado com pouca memória ou você tem que replicar através de alguma ligação 9600bps muito lento) ele provavelmente não vai valer a pena as dores de cabeça que você pode acabar com. Ter que escrever todos esses casos especiais em suas consultas pode ficar chato.

exemplo rápido: fazer a junção entre duas tabelas onde se você quer se juntar baseia-se se o sinalizador isDefective é conjunto vai ser uma dor. Ser capaz de usar apenas uma das duas colunas sozinho é provavelmente o suficiente de um aborrecimento que você pode salvar, pelo menos para mim.

Outras dicas

Eu consideraria fazer uma única mesa para as caixas e o tipo de caixa de ser uma coluna da tabela de caixa. Isto simplificaria as relações e torná-lo fácil de ainda consulta para o tipo de caixa. Assim, o item da caixa só tem uma chave estrangeira para a boxId.

Eu uso o Hibernate chama Tabela- per-subclasse , então meu DB acabaria com 3 mesas para Caixas: Box, ShippingBox e ReturnBox. O FK em BoxItem apontaria para Box.

O que você está falando é relações polimórficas. A única identificação que pode fazer referência a várias outras tabelas. Existem várias estruturas que suportam este, no entanto, é (potencialmente) ruim para a integridade de dados (que pode ser uma discussão completamente diferente ou não o seu banco de dados ou a sua aplicação deve manter a integridade referencial).

O que sobre isso?

BoxItem:
BoxItemID, Description, IsDefective

Box:
BoxID, Description

BoxItemMap:
BoxID, BoxItemID, BoxItemType

Em seguida, você pode ter BoxItemType ser uma enumeração, ou um inteiro onde você definir constantes em seu aplicativo como "Return" ou "envio" como o tipo de caixa.

Combine sobre a discussão polimórfica acima, embora tenha potencial para ser usado mal, ainda é uma solução viável.

Basicamente, você tem uma tabela base caixa chamada. Então você tem duas outras mesas, caixa e retorno transporte. Aqueles dois adicionar quaisquer campos extras que são especiais para eles. eles estão relacionados com a caixa com um 1:. mesa de base 1 fk.Boz tem os campos comuns de todos os tipos de caixa

Você se relaciona BoxItem com o quadro de caixa. A forma, você obter o tipo de caixa adequado é fazendo uma consulta que associa a caixa de criança com a caixa de raiz com base na chave. O registro que tem tanto a caixa de base e caixa de criança é desse tipo.

Você apenas tem que ter cuidado como mencionou que quando você criar um tipo de caixa que é feito corretamente. Mas isso é o que o teste é para. O código para adicionar-lhes apenas precisa ot escrito uma vez. Ou usar um ORM.

Suporte Quase todos da ORM esta estratégia.

Eu iria com apenas uma única tabela BoxItems com IsDefective, ShippingBoxID, os campos relacionados com o transporte marítimo de caixa, ReturnBoxID e os campos relacionados com o retorno-box. Alguns campos sempre será NULL para cada registro.

Este é um projeto muito simples e evidente que a próxima desenvolvedor é improvável de ser confundido por. Em teoria, este projeto é ineficiente por causa dos campos vazios garantidos para cada linha. Na prática, os bancos de dados tendem a ter um tamanho de armazenamento mínimo exigido para cada linha de qualquer maneira, então (a menos que o número de campos é enorme) este projeto é tão eficiente quanto possível de qualquer maneira, e muito mais fácil de código.

Eu provavelmente ir com:

BoxTable:
box_id, box_descrip, box_status_id ...
     1, Lovely Box, 1
     2, Borked box, 2
     3, Ugly Box, 3
     4, Flammable Box, 4

       BoxStatus:
       box_status_id, box_status_name, box_type_id, ....
                   1,Shippable, 1
                   2,Return, 2
                   3,Ugly, 2
                   4,Dangerous,3

                BoxType:
                box_type_id, box_type_name, ...
                          1, Shipping box, ...
                          2, Return box, ....
                          3, Hazmat box, ...

Dessa forma, a caixa de status define o tipo de caixa, e é flexível, se você precisa se expandir para alguns níveis de status mais ou tipos de caixa mais tarde.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top