Domanda

Okay, quindi sto preparando un tavolo per " Box Items " ;.

Ora, un articolo in scatola, a seconda di ciò che viene utilizzato per / lo stato dell'articolo, può finire per essere correlato a una "Spedizione". casella o a " Resi " di dialogo.

Un Articolo Box può essere difettoso: in tal caso, verrà impostato un flag nella riga dell'articolo Box (IsDefective) e l'oggetto Box verrà inserito in un " Resi " box (con altri articoli da restituire a quel fornitore). Altrimenti, l'articolo in scatola verrà eventualmente inserito in una "Spedizione". scatola (con altri articoli da spedire). (Nota che le scatole di spedizione e di reso hanno le loro tabelle: non esiste una tabella comune per tutte le scatole ... anche se forse dovrei considerare di farlo se possibile come terza possibilità?)

Forse non sto pensando chiaramente oggi, ma ho iniziato a mettere in discussione ciò che dovrebbe essere fatto in questa situazione.

Il mio istinto mi dice che dovrei avere un campo separato per ogni possibile relazione, anche se solo una delle relazioni può avvenire in un dato momento, il che renderebbe lo schema per gli elementi della scatola simile:

BoxItemID Descrizione IsDefective ShippingBoxID ReturnBoxID ecc ...

Ciò renderebbe chiare le relazioni, ma sembra dispendioso (poiché solo una delle relazioni verrà utilizzata in qualsiasi momento). Quindi ho pensato di poter avere un solo campo per BoxID e determinare a quale BoxID si riferiva (un ID casella di spedizione o di reso) in base al campo IsDefective:

BoxItemID Descrizione IsDefective BoxID ecc ...

Questo sembra meno dispendioso, ma non è adatto a me. La relazione non è ovvia.

Quindi, te lo dico io, guru del database di Stackoverflow. Cosa faresti in questa situazione?

EDIT: grazie a tutti per il vostro contributo! Mi ha dato molto da pensare. Per uno, userò un ORM la prossima volta che avvierò un progetto come questo. =) Per due, dato che non sono in questo momento, morderò i quattro byte e userò due campi.

Grazie ancora a tutti!

È stato utile?

Soluzione

Sono con Psychotic Venom e mattlant.

Seguire il percorso polimorfico (dover capire a quale tabella punta la tua chiave esterna in base al contenuto di un altro campo) sarà una seccatura. Codificare i vincoli per quello forse difficile (non sono sicuro che la maggior parte dei database lo sosterrebbe in modo nativo, penso che dovresti usare un trigger).

Gli oggetti si spostano mai tra le tabelle? Attaccare con due tabelle con definizioni identiche in cui uno è per i resi e uno per la spedizione può essere il percorso più semplice. Se si desidera attenersi alla definizione proposta per la prima volta (con i due campi separati) è perfettamente ragionevole.

" L'ottimizzazione prematura è la radice di tutti i mali " e tutto questo. Anche se sembra dispendioso, ricorda cosa stai memorizzando. Poiché sono ID, probabilmente sono solo numeri interi, forse 4 byte. Sprecare quattro byte per record è praticamente nulla. Infatti, a causa dell'imbottitura per mettere cose su indirizzi pari o altre cose del genere, potrebbe essere "gratuito". per mettere quel campo in più. Tutto dipende dal design del DB.

A meno che tu non abbia una buona ragione per seguire il percorso polimorfico (come se fossi su un sistema incorporato con poca memoria o devi replicare su un collegamento a 9600 bps molto lento) probabilmente non varrà la pena il mal di testa che puoi finire con. Dover scrivere tutti quei casi speciali nelle tue domande può diventare fastidioso.

Esempio rapido: fare un join tra due tabelle in cui se si desidera unirsi si basa se il flag isDefective è impostato sarà un problema. Essere in grado di usare solo una delle due colonne da solo è probabilmente una seccatura che potresti salvare, almeno per me.

Altri suggerimenti

Vorrei prendere in considerazione l'idea di creare una singola tabella per le scatole e il tipo di scatola sarebbe una colonna della tabella delle scatole. Ciò semplificherebbe le relazioni e semplificherebbe la ricerca del tipo di casella. Quindi l'elemento della scatola ha solo una chiave esterna per boxId.

Userei ciò che Hibernate chiama Table- per sottoclasse , quindi il mio DB verrebbe visualizzato con 3 tabelle per Box: Box , ShippingBox e ReturnBox . L'FK in BoxItem punta a Box .

Di cosa stai parlando sono le relazioni polimorfiche. Un singolo ID che può fare riferimento a più altre tabelle. Esistono diversi framework che supportano questo, tuttavia, è (potenzialmente) dannoso per l'integrità del database (che potrebbe essere un'altra discussione se il database o l'applicazione devono mantenere l'integrità referenziale).

Che dire di questo?

BoxItem:
BoxItemID, Description, IsDefective

Box:
BoxID, Description

BoxItemMap:
BoxID, BoxItemID, BoxItemType

Quindi BoxItemType può essere un'enumerazione o un numero intero in cui si definiscono le costanti nell'applicazione come " Return " oppure " Spedizione " come tipo di scatola.

Sono d'accordo sulla discussione polimorfica sopra, anche se ha il potenziale per essere usata male, è ancora una soluzione praticabile.

Fondamentalmente hai una tabella di base chiamata box. Quindi hai altri due tavoli, scatola di spedizione e scatola di ritorno. Quei due aggiungono tutti i campi extra che sono speciali per loro. sono correlati a box con una tabella di base 1: 1 fk.Boz ha i campi comuni di tutti i tipi di box.

Si collega BoxItem alla tabella box. Il modo in cui si ottiene il tipo di casella corretto è eseguendo una query che unisce la casella figlio alla casella principale in base alla chiave. Il record che ha sia nella casella base che nella casella figlio è di quel tipo.

Devi solo stare attento, come detto, quando crei un tipo di casella che sia fatto correttamente. Ecco a cosa serve il test. Il codice per aggiungerli deve essere scritto solo una volta. Oppure usa un ORM.

Quasi tutti gli ORM supportano questa strategia.

Andrei con una sola tabella BoxItems con IsDefective, ShippingBoxID, i campi relativi alla spedizione, ReturnBoxID e i campi relativi alla restituzione. Alcuni campi saranno sempre NULL per ogni record.

Questo è un design molto semplice e evidente che difficilmente il prossimo sviluppatore sarà confuso. In teoria questo design è inefficiente a causa dei campi vuoti garantiti per ogni riga. In pratica, i database tendono ad avere comunque una dimensione minima di archiviazione richiesta per ogni riga, quindi (a meno che il numero di campi non sia enorme) questo design è comunque il più efficiente possibile e molto più facile da codificare.

Probabilmente andrei con:

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, ...

In questo modo lo stato della scatola definisce il tipo di scatola ed è flessibile se è necessario espandersi in alcuni livelli di stato o tipi di scatola in seguito.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top