php e relazioni tra tabelle in pratica

  • Creatore Discussione Creatore Discussione Palbi
  • Data di inizio Data di inizio

Palbi

Nuovo Utente
16 Dic 2016
11
0
1
48
Ciao,
sto creando un semplice DB per accesso e configurazioni ad un sito.

CREATE TABLE `Utenti` (
`idutente` int(15) unsigned NOT NULL AUTO_INCREMENT,
`nomeutente` varchar(60) NOT NULL DEFAULT '',
`emailutente` varchar(60) NOT NULL DEFAULT '',
`passwordutente` varchar(60) NOT NULL DEFAULT '',
PRIMARY KEY (`idutente`)
) ;

CREATE TABLE `preferenzeutente` (
`idutente` int(15) unsigned NOT NULL,
`idlingua` int(11) DEFAULT NULL,
// altre preferenze.......
PRIMARY KEY (`idutente`),
CONSTRAINT `relazioneutentepreferenza` FOREIGN KEY (`idutente`) REFERENCES `Utenti` (`idutente`)
) ;


quello che non riesco bene a comprendere, e non trovo qualcosa di chiaro in rete, è come gestire le relazioni a livello di codice intendo, a livello pratico.
Il codice qui sopra è una relazione 1:n? se la volessi 1:1? o n:m?
constraint, esattamente, cosa serve?

grazie mille!!
 
costraint, in questo caso, è la clausola che lega in modo "indissolubile" la tabella preferenze alla tabella utenti

non puoi scrivere nella tabella preferenze un elemento che non sia già esistente nella tabella utenti

così come non puoi cancellare un elemento da utenti se esiste nella preferenze
a meno che tu non aggiunga "ON DELETE CASCADE" sulla preferenze in modo da rendere automatica la cancellazione
conseguente ad una cancellazione in utenti

volendo che nella tabella preferenze ci sia un solo elemento per ciascun utente, in questo caso è
"PRIMARY KEY (`idutente`)" che rende univoca la colonna, essendo essa definita come chiave primaria

in generale, quando vuoi che un elemento sia "univoco" e non è chiave primaria, puoi definire
CONSTRAINT [nomeindice] UNIQUE KEY ( [colonna5] ASC, [colonna2] ASC )
quindi anche comprendendo + colonne in un ordine logico che vede la colonna più "spezzata" come primo elemento, a seguire le altre con lo stesso criterio
è probabile che un insieme così definito sia poi elemento di ricerca trovandolo così già indicizzato

tutte queste relazioni rendono il db "consistente" ovvero se intervenissero altre persone, non avrebbero possibilità di commettere errori, oltre a ricordare a me, persona di poca memoria, le regole dello specifico db

dalla struttura di utenti, credo tu stia pensando di trovare gli elementi con una select di "emailutente"
ricorda che se non indicizzi questa colonna della tabella utenti, avrai accessi di lettura sequenziali
ovvero per ogni "select emailutente" viene letta tutta la tabella con buona pace delle prestazioni

probabile che "emailutente" sia da definire chiave univoca

sufficiente ?
 
Ultima modifica:
Ciao, grazie mille. Si ... credo... comunque mi hai dato già due dritte che non avevo considerato.
provo a buttare giù codice e lo posto, se hai un minuto per leggerlo e darmi un consiglio te ne sarei gratissimo.
grazie ancora.
 
ciao, quanto sono distante? :)




CREATE TABLE `Utente` (

`idutente` int(15) unsigned NOT NULL AUTO_INCREMENT,

`nomeutente` varchar(60) NOT NULL DEFAULT '',

`emailutente` varchar(60) NOT NULL DEFAULT '',

`passwordutente` varchar(60) NOT NULL DEFAULT '',

INDEX (‘idutente’,’emailutente’),

PRIMARY KEY (`idutente`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `preferenzeutente` (

`idutente` int(15) unsigned NOT NULL,

`idlingua` int(11) DEFAULT NULL,

//altre preferenze

PRIMARY KEY (`idutente`),

CONSTRAINT `utentepreferenze` FOREIGN KEY (`idutente`) REFERENCES `Utente` (`idutente`) ON DELETE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `macchina` (

`idmacchina` int(15) unsigned NOT NULL,

`idutente` int(15) unsigned NOT NULL,

‘tipomacchina’ varchar(10) NOT NULL DEFAULT ''

‘nridentificativomacchina’ varchar(10) NOT NULL DEFAULT '',

//altri dati macchina

PRIMARY KEY (`idmacchina`),

REFERENCES `Utente` (`idutente`) ON DELETE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `Lingua` (

`idlingua` int(11) unsigned NOT NULL AUTO_INCREMENT,

`nomelingua` int(11) NOT NULL,

PRIMARY KEY (`idlingua`)

CONSTRAINT `lingua` FOREIGN KEY (`preferenzeutente`) REFERENCES `preferenzeutente` (`idlingua`) ON DELETE CASCADE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;



CREATE TABLE `precedentiproprietari` (

`idmacchina` int(11) unsigned NOT NULL,

`idutente` int(11) unsigned NOT NULL

PRIMARY KEY (`idmacchina`,`idutente`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;


schema:
 

Allegati

  • image1.jpg
    image1.jpg
    654,7 KB · Visite: 273
TABLE `Utente`

INDEX (‘idutente’,’emailutente’) perchè ? quando fai la ricerca conosci idutente oltre a conoscere l'email ?

penso che cercherai email per ottenere idutente e le altre info, quindi forse meglio scrivere INDEX (’emailutente’) con,
PHP:
select * from utente u, preferenzeutente p where p.idutente=u.idutente and emailutente='xyz'
ammesso che al momento della memorizzazione iniziale dell'utente si inseriscano contestualmente le informazioni aggiuntive altrimenti meglio usare una join

come vedi, la progettazione del db non può prescindere dalla logica della gestione

cerca sempre di non usare maiuscole, spazi o caratteri "strani" nei nomi se non per "forti" motivi, in questo modo eviti di usare le virgolette storte (scusa non ricordo mai come si chiamano) in modo da rendere più chiaro il codice, meno virgolette, più comprensione, a meno che non lo richieda espressamente mySQL (che non conosco)

TABLE `preferenzeutente`, TABLE `Lingua`

hai definito due indici identici, la chiave primaria ed il legame con utenti,
eviterei la chiave primaria, spazio e gestione inutile, lascerei solo il legame con utenti

seconso me avresti dovuto definire qui
PHP:
CONSTRAINT `lingua` FOREIGN KEY (`preferenzeutente`) REFERENCES `preferenzeutente` (`idlingua`) ON DELETE CASCADE
ovviamente con le referenze corrette, perdona il mio copia incolla
la tabella lingue è (credo) una tabella di riferimento e controllo, deve impedire di inserire nella colonna corrispondente una lingua che non esiste, ma,
se cancelli una lingua non puoi cancellare l'elemento, quindi sarà il software che andrai a sviluppare che dovrà farsi carico del giusto controllo e delle giuste operazioni


poi eviterei di inserire l'id della lingua ma inserirei direttamente il codice magari definito alfa(numerico) in modo che chi dovesse fare una query estemporanea capisca dal contenuto del campo quello che deve cercare, chiarezza nelle cose

un appunto, non ho mai capito a cosa serva inserire in tutte le tabelle un valore "autoincrement", esempio nella tabella lingue a che serve ?
il codice della lingua dovrebbe essere univoco ed è chiave di ricerca
'de-AT'
'de-CH'
'de-DE'
a me sembra sufficiente, inutile sovraccaricare con indici inutili

NOT NULL DEFAULT '' ma il default mi sembra un null o sbaglio ?

se io avessi male interpretato la logica, perdona e cestina tutto
altrimenti prova a rivedere "lingua", "utenti" e "preferenzeutenti"
 
Ciao Marino,
obbligato. ti ringrazio molto. Mi stai dando molti spunti. Ora provo a rivedere la struttura.

grazie ancora!
 

Discussioni simili