Consigli su una progettazione di base, progettazione del database per la prima volta


8

Sto seguendo un corso per diventare uno sviluppatore Java.

Il corso prevede l'utilizzo di database, ma sfortunatamente non ne progettiamo davvero nessuno.

Il più delle volte otteniamo database prefabbricati e dobbiamo implementare il codice su di esso per inserire, aggiornare, leggere o eliminare i dati.

Ma quando arriverà il mio test finale, è probabile che realizzerò qualcosa che coinvolge un database e quindi voglio provare a progettarne alcuni più piccoli per ottenere il blocco di una progettazione poiché ho notato che una buona progettazione di database fa molta differenza quando scrivendo il codice per lavorare con esso.

Spero che questo tipo di domande sia consentito qui e che non sarà troppo ampio.


Questo è un piccolo design che ho realizzato per qualcosa di semplice come clubse memberscon addressese phonenumbers.

  • Ci saranno più club.
  • Ogni club avrà più membri (ovvio)
  • Un socio non può far parte di più club
  • Un membro può avere più numeri di telefono e indirizzi e-mail
  • Un membro può avere un solo indirizzo
  • Un indirizzo può appartenere a membri diversi (coppie o fratelli)

Le mie più grandi confusioni:

  • Se voglio aggiungere una colonna Clubche descriva il proprietario, che sarà anche un membro, qual è l'approccio migliore senza avere lo stesso membro elencato due volte?

  • Dovrei mettere tutte le mie tabelle sull'incremento automatico di un ID o sarebbe una cattiva idea? (Vantaggi / svantaggi?)

  • Se aggiungo chiavi esterne nella scheda Chiavi esterne, queste corrisponderanno automaticamente alla tabella corretta o devo aggiungere anche queste alle colonne? (vedi foto 2)

  • E la mia domanda probabilmente più assurda a tutti ... Metto le chiavi esterne phonenumbere emailnella loro rispettiva tabella che si collega a una persona_Id o devo inserire il numero di telefono e l'ID e-mail nella tabella persona?

(Mi scuso per la lingua delle immagini che non è l'inglese, spero che questo non sia un grosso problema)

Design

Chiavi esterne

Risposte:


11

Risposte alle tue domande individuali

Se voglio aggiungere una colonna Clubche descriva il proprietario, che sarà anche un membro, qual è l'approccio migliore senza avere lo stesso membro elencato due volte?

Se —come indicato nelle vostre specifiche a Person can be a Member of only one Club— e siete interessati a memorizzare questo dato semplicemente come vero o falso , un'opzione è aggiungere una BIT(1)o una colonna BOOLEAN( TINYINT) alla Persontabella e potreste voler chiamare questa colonna IsClubOwner. In questo modo, è possibile registrare il fatto che una determinata persona è il proprietario di un club solo una volta. A parte questo, questo metodo offre anche la possibilità di trattenere diverse persone come proprietari dello stesso club . Puoi vedere una rappresentazione a livello logico di questo approccio nella Figura 1 .

Tuttavia, stai cercando l'approccio migliore e, secondo la mia esperienza, tale approccio comporta lo sviluppo di una struttura molto più espandibile e versatile. A questo proposito, segui la progressione di un esercizio di modellizzazione per questi e altri punti di seguito, nelle sezioni intitolata "Copertura delle specifiche rimanenti", "Persona come membro di più club" e "Membro e proprietario come tipi di entità separati".

Dovrei mettere tutte le mie tabelle sull'incremento automatico di una ido sarebbe una cattiva idea? (benifits / svantaggi?)

Se dovete affrontare un esplicito requisito che indica la definizione di una tabella con una colonna di tali caratteristiche, e tale colonna ha un significato contestuale valida o serve uno scopo particolare come essere un surrogato per una vasta PRIMARY KEY naturale (PK), allora sì, dovresti procedere in questo modo.

Altrimenti, se non hai detto requisito, ritengo che sarebbe inutile poiché devi archiviare e gestire una colonna aggiuntiva senza significato e (forse?) Anche un INDICE aggiuntivo nel tuo database.

Come al solito, è necessario analizzare ciascun caso insieme alle sue ripercussioni generali per decidere come procedere.

Se aggiungo chiavi esterne nella scheda Chiavi esterne, queste corrisponderanno automaticamente alla tabella corretta o devo aggiungere anche queste alle colonne?

A questo proposito, il mio consiglio per te è quello di creare manualmente la struttura del tuo database, di codificare le tue DDLdichiarazioni fino a quando non hai una solida conoscenza dell'argomento. Se lo fai, sarà più facile per te capire i processi che gli strumenti grafici stanno eseguendo "sotto il cofano".

Per me, ad esempio, creando un'affermazione come la seguente:

CONSTRAINT FK_PersonPhoneNumber_to_Person FOREIGN KEY (PersonId)
REFERENCES Person (PersonId)

È molto più istruttivo dell'utilizzo degli strumenti della GUI per eseguire questo tipo di attività, soprattutto ora che stai costruendo i tuoi primi progetti.

E la mia domanda probabilmente più rumorosa di tutte ... Metto le chiavi esterne di phone_numbere emailnella loro rispettiva tabella che si collega a una person_ido dovrei mettere phone_numbere email idsnella tabella persona?

Personalmente, penso che questa e tutte le altre domande siano completamente valide e ben contestualizzate .

Tornando agli aspetti tecnici che ci riguardano, questa indagine precisa offre una buona opportunità per rivedere le due seguenti affermazioni:

  • A Person can be reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber can be used to reach one-to-many People

Quindi, si può concludere che esiste una relazione molti-a-molti tra Persone PhoneNumber, quindi, suggerisco la creazione di una tabella associativa denominata PersonPhoneNumberper rappresentare detta relazione nel database. Il PK di questa tabella dovrebbe essere composto da due colonne diverse: PersonId(un KEY ESTERO [FK] che punta a Person.PersonId) e PhoneNumber(un FK che fa riferimento a PhoneNumber.Number). Per una descrizione del livello logico di tutto quanto sopra, vedere la Figura 1 .

D'altra parte, esaminiamo le due proposizioni che seguono:

  • A Person can be contacted via zero-one-or-many EmailAddresses
  • An EmailAddress can be used to contact exactly one Person

Quindi, sì, è necessario impostare un riferimento alla FK Persondal EmailAddresstavolo, e questo tavolo dovrebbe avere una PK composito troppo, che sarebbe composta da colonne PersonIde Address. In questo modo, puoi assicurarti che la stessa combinazione di EmailAddress.PersonIde EmailAddress.Addresspossa essere inserita una sola volta.

Se desideri anche assicurarti che un dato EmailAddres.Addresspossa essere archiviato in una sola riga, devi solo stabilire un VINCOLO UNICO per questa colonna.

Modelli di dati logici proposti

Per esporre più chiaramente i miei suggerimenti, ho incluso quattro distinti modelli logici IDEF1X [1] che sono mostrati in Figura 1 , Figura 2 , Figura 3 e Figura 4 . Fornirò una spiegazione delle funzionalità più rilevanti visualizzate in ognuna di esse nelle sezioni corrispondenti. Puoi anche scaricare da Dropbox un PDF che integra in un singolo modello la maggior parte degli elementi in discussione.

Coprendo le tue restanti specifiche

Relativi a persone e indirizzi

Esaminiamo le due seguenti affermazioni (leggermente riformulate) che sono rilevanti per le persone e gli indirizzi :

  • A Person can only have one Address
  • An Address can belong to different People (couples or siblings)

Quindi, per far fronte a queste restrizioni, puoi scegliere di implementare un modello di dati simile a quello che puoi vedere nella Figura 1 .

Fig. 1. Modello di dati di club e soci - Prime specifiche

Tenendo conto del modello indicato, è necessario seguire i passaggi seguenti:

  1. Crea una tabella chiamata PersonAddressfissando una relazione tra Persone Address. Imposta le colonne PersonIde AddressIdcome PK composto di questa tabella.

  2. Configurare un VINCOLO UNICO per la PersonAddress.PersonIdcolonna per garantire che un valore specifico possa essere inserito al massimo in una riga di detta tabella. A livello logico, questa circostanza implica che PersonAddress.PersonIdè diventato un ALTERNATE KEY [2] .

  3. Se il valore di AddressIdin un determinato PersonAddresstentativo di inserimento non è già stato memorizzato, quindi lasciare che l'inserimento continui, altrimenti, quando tale valore esiste già in una riga, è necessario verificare che (a) PersonIdchi ha registrato che AddressIdsia anche registrato come Marriage.WifeIdse PersonIdè un maschio (dato derivato tramite Person.GenreCode) o (b) che PersonIdè il Marriage.HusbandIdquando PersonIdè una femmina (derivata anche in virtù di Person.GenreCode). Se una di queste condizioni è soddisfatta nella situazione appropriata, allora si dovrebbe lasciare andare INSERT.

  4. Se le condizioni di cui sopra non sono state soddisfatte, c'è ancora la possibilità che un PersonAddressinserimento tenti di avere successo. Devi verificare che il PersonIdvalore coinvolto in detto inserimento provi a condividerne almeno uno Progeny.ParentIdcon quello PersonIdche ha già registrato il file PersonAddress.AddressId. Se questa condizione è soddisfatta, significa che sono archiviati come Siblingsnel database, quindi INSERT deve avere esito positivo.

Come in qualsiasi implementazione di database relazionale, dovresti prendere seriamente in considerazione di eseguire le tue DMLoperazioni all'interno di Transazioni ACID in modo da poter proteggere l' integrità e la coerenza dei dati con cui stai lavorando.

Partecipare ai requisiti che hai aggiunto nei commenti: indirizzi e numeri di telefono che servono sia i club che le persone

A condizione che si desideri dare la possibilità a indirizzi e numeri di telefono di servire sia persone che club , è possibile utilizzare una relazione supertipo-sottotipo . Ecco una risposta in cui do un trattamento più dettagliato a questo tipo di strutture, nel caso tu sia interessato.

Nel presente scenario, è possibile definire Persone Clubcome sottotipi di una nuova entità denominata Party, un termine comunemente usato negli ambienti legali per indicare (a) una persona o (b) un gruppo di persone (come indicato nel senso n. 6 ). Con questo metodo, le relazioni tra Addresses(o PhoneNumbers) e Peoplee Clubssarebbero definite attraverso Partyil supertipo. Vedere la Figura 2 per una rappresentazione di questo suggerimento.

Fig. 2. Modello di dati di club e soci - Seconda specifica

Parte e indirizzo

Quindi possiamo leggere in questo nuovo modello che:

  • A Party keeps zero-one-or-many Addresses
  • An Address is kept by one-to-many Parties

Pertanto, esiste una relazione molti-a-molti che coinvolge Partye Addressche si esprime attraverso l' PartyAddressentità.

Numero di parte e telefono

Inoltre, possiamo interpretare che:

  • A Party is reached through zero-one-or-many PhoneNumbers
  • A PhoneNumber is used by one-to-many Parties

Ecco perché ho aggiunto l' PartyPhoneNumberentità che descrive l'associazione molti-a-molti che ha effetto tra i tipi di entità Partye PhoneNumber.

Partito e club o persona

Quindi, si può anche leggere che:

  • A Party is either a Club or a Person

Quindi, Partyfornisce un collegamento da uno Clubs o People a Addresses(o PhoneNumbers).

Persona come membro di più club

Come menziona @aldwinaldwin nella sua risposta, se si desidera fornire la funzionalità affinché una persona sia membro di più club , è possibile includere un tavolo chiamato ClubMemberche fungerebbe da un'altra relazione molti-a-molti, questa volta, naturalmente , interconnessione Persone Club.

Aggiungerò a quanto sopra che questa tabella può anche essere utile nell'obiettivo di memorizzare qualsiasi persona concreta come proprietario di più club , mediante l'inclusione della IsClubOwnercolonna booleana già menzionata . In effetti, si può dire che questa nuova tabella è la rappresentazione di un tipo di entità integrale a sé stante.

Come dimostrato nella Figura 3 , tale tabella richiede un PK composto composto da colonne ClubIde MemberId(un nome di ruolo [3] assegnato a PersonId), e queste colonne devono essere definite anche come FK che puntano, corrispondentemente, a Clube Person.

Fig. 3. Modello di dati di club e soci - Persona come membro di più club

Una struttura più adattabile

Utilizzando questa impostazione è anche possibile rispettare la regola iniziale che stabilisce che a Person can be a member of only one Club, ma è sufficiente aggiungere un VINCOLO UNICO alla MemberIdcolonna, in modo che un determinato valore possa essere inserito in non più di un'occasione. Quindi, come puoi notare, questa struttura è molto più adattabile di quella mostrata in Figura 1 , poiché rilasciando il Vincolo UNICO (o INDICE) apriresti la funzionalità di cui sopra per consentire a una persona di diventare un membro di diversi club del contemporaneamente.

Membro e proprietario come tipi di entità separati

Come sapete, l'archiviazione di diversi fatti sul ruolo svolto da una persona come proprietario di un club - a parte la sua semplice esistenza in un attributo vero o falso - può essere molto vantaggioso. Ad esempio, potresti voler mantenere la data effettiva in cui una persona definita è diventata il proprietario di un club , quindi puoi gestire questa situazione introducendo un tipo di entità separato chiamato ClubOwner, come presentato nella Figura 4 .

Fig. 4. Modello di dati di club e soci - Membro e proprietario come tipi di entità separati

Una volta costruito un tavolo basato su questo nuovo tipo di entità, è possibile aggiungere le colonne di adattamento che rappresentano le caratteristiche che entrano in gioco esclusivamente quando a Personè il Ownerdi a Club. Come illustrato, questa tabella conterrebbe un PK composto dalle colonne FK che fanno riferimento Person.PersonIde Club.ClubId, in questo modo, qualsiasi combinazione di ClubOwner.OwnerId(o ClubOwner.PersonId, se preferisci) e ClubOwner.ClubIdpuò essere inserita in una sola opportunità.

Naturalmente, con questa configurazione è ancora possibile derivare in forma booleana se a Personè il Ownerparticolare di un particolare Clubcon l'aiuto di una query che restituisce un valore scalare che può essere valutato come vero o falso .


Appunti

1. Integration Definition for Information Modeling ( IDEF1X ) è una tecnica di modellazione dei dati altamente raccomandabile che è stata definita come standard nel dicembre 1993 dal National Institute of Standards and Technology ( NIST ) degli Stati Uniti . Si è solidamente basata su (a) alcuni dei documenti teorici scritti da creatore del modello relazionale , vale a dire, il Dr. EF Codd ; su (b) la teoria Entità-Relazione , sviluppata dal Dott. PP Chen ; e anche su (c) la tecnica di progettazione del database logico , creata da Robert G. Brown . Vale la pena notare che IDEF1X eraformalizzato mediante la logica del primo ordine .

2. Una chiave alternativa è un attributo (o una combinazione di attributi) che contiene valori che identificano in modo univoco un'occorrenza di entità ma non è stato scelto come PK del tipo di entità pertinente; ogni tipo di entità può avere zero, uno o più TASTI ALTERNATIVI. In un modello IDEF1X, sono indicati come "AK" più il rispettivo numero, ad esempio AK1, AK2, ecc. Di solito sono implementati in una struttura DDL SQL tramite un VINCOLO UNICO (o un INDICE UNICO ).

3. I nomi dei ruoli sono denotazioni (o alias) assegnati agli attributi FK per esprimere il significato che ricoprono nell'ambito delle rispettive entità. Il loro utilizzo è raccomandato dal 1970 dal dott. Codd nel suo documento fondamentale intitolato "Un modello relazionale di dati per grandi banche dati condivise" . Da parte sua, IDEF1X - mantenere la fedeltà riguardo alle pratiche relazionali - sostiene anche la denominazione dei ruoli.


2
  1. Se un proprietario è sempre un membro del suo club. Aggiungi ownerId al tavolo del Club e inserisci l'identificativo person del membro proprietario.
  2. L'incremento automatico di un ID è buono. È possibile aggiungere un altro campo "codice", lì inserire il codice soci sulla tessera club.
  3. Dovrebbe essere automaticamente ok (penso)
  4. Inserisci personId in Numeri di telefono e tabella e-mail.

... Non puoi essere membro di più club? Se puoi, crea un tavolo ClubMember con clubId e personId. In questo modo puoi connettere una persona a più club.


1
Cosa succede se desidero che il mio club abbia un numero di telefono? inserisco anche il numero clubIddi telefono e lascio il club o la persona impostati su null?
Vahx,

Non separerei eccessivamente tutti gli oggetti (normalizzazione dei dati). Metti solo 1 numero di telefono nel tavolo del club. La normalizzazione è buona, ma troppa normalizzazione può causare problemi.
aldwinaldwin,

1
ma supponiamo che io voglia fare questo? Prenderò l'indirizzo come esempio, i soci hanno un indirizzo ma anche i club avranno bisogno di un indirizzo
Vahx

1
Crea un record di indirizzo e metti l'indirizzoId nel club. Poiché un club ha 1 indirizzo, un socio ha 1 indirizzo. Per i numeri di telefono, devi inserire personId nel numero di telefono per avere da 1 a molti. ..... Potresti creare un table personPhoneNumber (personId, phonenumberId) + table clubPhoneNumber (clubId, phonenumberId) ciò che lo rende più una relazione molti-molti.
aldwinaldwin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.