Newsgroup: it.comp.lang.visual-basic
Titolo: Come devo fare il DB?

Ciao
Per favore, mi potete dare un suggerimento per creare/usare un DB? ...il
quale contenga dati del tipo:
Mucca = appartiene alla categoria cornuti, ma anche alla categoria
*quadrupedi*, ma anche alla categoria ruminanti, ma anche alla categoria
mammiferi
Lucertola = appartiene alla categoria *quadrupedi* (come la mucca), ma anche
alla categoria rettili, ma anche alla categoria *squamati* etc..
Pesce rosso = appartiene alla categoria *squamati* (come la lucertola), ma
anche alla categoria pesci, ma anche alla categoria pinne, occhi,
vattellapesca etc...
...and so on... :-)
...in modo che la ricerca dei dati, in seguito, sia del tipo: "Cerca tutti
quadrupedi, squamati, con occhi" etc....
Il mio problema (sono qui... dato che non sono avvezzo allo stesso) sta nel
fatto che le categorie di appartenenza possono aumentare con l'andar del
tempo.
In realtà, 'sta roba, mi serve per raccogliere della normtiva; quindi queste
potrebbero appartenere a più categorie (anche legate tra loro) e, durante
l'inserimento delle stesse norme, avrò la necessità di dover creare delle
nuove cetegorie.
Come devo fare?
Uso VB6 con ADO (....che non ricordo più, perchè non lo uso da un paio di
anni!) :-D
Grazie ottocento :-)
-- 
Bye
MioMao

 mammiferi
[cut]
Rallegrati, se non altro e' qualcosa di semplice da risolvere :-)
(nomi piu' o meno a caso, seguendo il tuo esempio)
Primo: tabella Animali, con l'elenco degli animali e di tutte le loro 
caratteristiche TRANNE le categorie. Con campo chiave numerico.
Secondo: tabella Categorie, che contiene l'elenco di tutte le categorie. Con 
campo chiave numerico.
Terzo: tabella Animali_Categorie, con tre colonne, una per l'IDAnimale e 
l'altra con l'IDCategoria (l'altra e' una chiave di riga...qualcuno ti dira' 
che e' sbagliato, ma io preferisco cosi')
Ogni animale avra' piu' righe, con IDAnimale uguale ma IDCategoria 
differente.
In questo modo hai massima flessibilita' con minima ridondanza. E le query 
vengono fuori che e' un piacere.
(ad esempio, potresti anche decidere che piu' di 50 categorie un animale non 
le ha, e quindi creare 50 campi Categoria nella tabella degli animali. Lo 
spreco di memoria e' minimo -quello di prestazioni leggermente piu' alto, 
invece- ma poi ti voglio vedere a fare una query di Join su 50 campi che per 
un'animale ti tiri fuori i nomi delle categorie :-D

 Rallegrati, se non altro e' qualcosa di semplice da risolvere :-)
Bene! :-)
Ricordavo (solo) che non è complesso... ma (mi scuso per la mia 
ignoranza in materia) davvero non uso i DB da molto tempo e proprio non 
ricordo una solenne mazza... :-))
Per mettimi di ringraziarti (molto). Mi hai rinfrescato la memoria e 
chiarito rapidamente il tutto :-)
Ora preparo il DB di partenza (questo dovrei riuscire a farlo.. un 
barlume di memoria al rifuardo c'è ancora eheheehe) :-)   poi provo a 
mettere insieme i primi dati.
Poi avrò lo scoglio della Select :-D ...dimenticata pure questa.. Vabbè, 
pasiensa, non è difficile... rispolvero qualche fetenzia tra i miei 
vecchi programmini.. e prima o dopo ci riuscirò, lo sento! :-))
Grazie ancora, Drizzt! :-)
(hey se incapperò in qualche mia ottusità, ti scriverò ancora, neh!) :-)
Bye
MioMao

 che e' sbagliato, ma io preferisco cosi')
Pliz, mi spieghi a cosa serve la terza colonna "chiave di riga"?
Per l'indicizzazione? (è sempre numerica, giusto?)
Bye
MioMao

 differente.
Bon... .il Db è fatto... il programmino è quasi terminato (funziona. Ma 
ho faticato quasi come un matto... NON ricordavo più nulla! Manco 
l'esistenza di .update o l'uso di .seek!) :-D
Una cosa che ancora non ricordo (oppure, che non mi è chiara) è l'indice 
, la sua creazione e l'uso.
Cioè, con il VisData, ho creato i campi (es: IDanimale di tipo long, 
IDcategoria di tipo long).. tu parli di "chiave di riga".
Ma... in realtà che devo fare?
Devo creare un'altro campo (IDvattellapesca, come chiave primaria?), 
oppure ti riferivi ad un indice?
E, se è indice, come lo devo creare? (cioè... basta un indice, riferito 
a IDanimale+IDcategoria? Oppure uno a testa, per ognuno di loro? O...cosa?)
Inoltre... poi come lo devo usare, in VB6?
Grazie (a te e a chi vorrà intervenire). :-)
Bye
MioMao

 Inoltre... poi come lo devo usare, in VB6?
Argomento, almeno per me, spinoso.
1) Hai bisogno, per ogni tabella, di un qualcosa che identifichi 
univocamente ogni riga. La chiave, appunto (ho detto chiave di riga, ma era 
per intenderci).
Gli indici NON sono chiavi. Un'indice e' un insieme di informazioni gestite 
automaticamente dal DB che permettono di accellerare le ricerce su una 
determinata colonna. Ad esempio, nel tuo DB, nella tabella 
Animali_Categorie, la colonna IDAnimale dovrebbe avere un indice. In questo 
modo quando cerchi un determinato ID la ricerca sara' piu' veloce.
Per quanto riguarda le chiavi...credo che il 99% dei programmatori userebbe 
come chiave della tua tabelle la coppia IDAnimale+IDCategoria.
Ora, visto che a me e' sempre piaciuto invece ottimizzare le prestazioni a 
discapito delle dimensioni, e che al giorno d'oggi un campo in piu' non 
ammazza nessuno, preferisco inserire in ogni tabella una campo contatore che 
faccia da chiave univoca. Piu' veloce e non di poco.
Tutto li', preferenze mie personali...
Ah, in VB6 questa roba dovrebbe essere usata automaticamente. Nel senso che 
se fai una query di select con lo where su un campo indicizzato, e' il 
motore del db che usa l'indice per fare piu' velocemente la ricerca.

 motore del db che usa l'indice per fare piu' velocemente la ricerca.
Ok, ok... allora sparo indici in tutte le tabelle! :-))
Grazie ancora
Bye
MioMao

 faccia da chiave univoca. Piu' veloce e non di poco.
Oltre per il fatto che quando si fanno inserimenti non si deve sempre star
a vedere se quella chiave esiste già, o perlomeno lo si fa se è necessario,
altrimenti si incrementa automaticamente il contatore e via.
-- 
DBMS Firebird
VB6 + Ado

Ciao Drizzt
Ricordi i miei precendenti msgs, relativi al DB "categorie" etc... 
etc...?? :-)
Bene! Sono arrivato al dunque.
Pare funzionare..... QUASI tutto. :-)
Ora... non so come devo comporre la stringa di Select per fare in modo 
che l'OpenRecordset mi recuperi tutti i dati che appartengono a PIU' 
categorie.
Inizialmente pensavo che una cosa del genere...
"SELECT * FROM mioDB WHERE id_mio = 5 AND id_mio = 3;"
...potesse funzionare.
hemm... ma, visti i risultati... è evidente che non funziona! :-D
In linea di massima, ti dico come ho impostato le tabelle del DB:
Categorie
	id_cat LONG (incrementale-autom.)
	str_cat STRING * 50
	indice impostato su id_cat
Descrizione
	id_des LONG (incrementale-autom.)
	str_des MEMO
	indice impostato su id_des
MioDB
	id_Ins LONG (incrementale-autom.)
	id_cat LONG
	id_des LONG
	indice impostato su id_cat+id_des
(se non vanno bene... fai un bel fischio, neh!) :-D
Nell'ultima tabella (nel esempio: MioDB) inserisco i dati relativi 
all'associazione tra i contenuti delle tabelle Categorie e Descrizione, 
in modo che un record di Descrizione appartenga a una o più Categorie.
Vorrei fare in modo che la Select mi possa recuperare contestualmente 
tutti gli appartenenti (ad es.) alla categoria 5 e alla categoria 3 (and 
so on...)
Come devo fare?
ri-Grazie  :-)
Bye
MioMao

 (se non vanno bene... fai un bel fischio, neh!) :-D
Cosi' a pelle...mi fa strano.
L'indice su un campo serve a rendere piu' veloci le ricerche su quel campo.
E credo che di solito cercarai tutte le id_cat per un dato id_des oppure 
tutte le id_des per un dato id_cat, giusto?
Quindi, in teoria, hai bisogno di due indici separati, uno per colonna, in 
modo che se cerchi un id_cat o un id_des la ricerca usi l'indice.
L'indice che comprende entrambe le colonne invece ha senso se le ricerche le 
fai cercando una coppia di id_cat/id_des particolare...
Non so' se sono riuscito a spiegarmi bene...

 Non so' se sono riuscito a spiegarmi bene...
Si, si.. benissimo.
Sembro tonto.
In realtà... sono solo un po' deficiente...
LOL :-D
-- 
Bye
MioMao

 LOL :-D
Rotfl :-D

 Rotfl :-D
:-D :-D
--
Bye
MioMao

 LOL
Eh?
Che roba sono gli AS?

 Che roba sono gli AS?
IBM...
Un amico, ogni tanto, mi racconta i suoi "letarghi" dai clienti.. .in attesa
degli eventi. :-)
Grazie ancora.
Ora me lo studio un poco... e poi ti faccio sapere i risultati :-)
-- 
Bye
MioMao

 WHERE (1c.IDb=2) AND ([1c_1].IDb=3)
Ok, ho sostituito i tuoi "simboli" con i miei... e mi recupera i dati, 
disciminando come prima (mia versione errata) NON faceva.
Grazie :-)
Ora, però (c'è sempre un "però" nella vita di ognuno di noi) :-)) 
...vorrei (se me lo permetti) capire MEGLIO l'aggeggio.
Soprattutto in funzione di ciò che vorrei fare.
Cioè... la SELECT, impostata in quel modo, recupera correttamente (e 
contemporaneamente) i dati  di.... solo DUE categorie.
Ma le categorie, nel mio stupido programmino, saranno "enne", cioè.. un 
numero variable da 1 a.... N (presumibilmente con N <= 5 o 6 categorie 
alla volta; solo un deficiente ricercherebbe quei dati con N>6) :-DD
Quindi, nel mio intento (o programma), uso una ListBox, impostata con la 
Style=1 (checkBox), in modo che dal suo elenco (le categorie), si 
possano selezionare quelle interessanti di fini della ricerca.
Quindi,
1) nel programmino, verifico quante categorie sono state selezionate 
nella ListBox
2) con un ciclo While costruisco la stringa di SELECT, aggiungendo gli 
ID corrispondenti alle categorie scelte (presi da una matrice ad-hoc)
In altre parole, procedo in questo modo:
1) imposto una Stringa = "Select... bla bla bla..." fino al primo ID da 
inserire
2) prelevo dalla matrice l'ID corrispondente alla categoria selezionata 
(che possiedono lo stesso indice, nella matrice della ListBox e nella 
matrice della mia variabile)
3) lo converto in stringa.. e lo accodo alla stringa della SELECT...
4) così via... finchè completo la stringa di SELECT... che poi passerò 
al OpenRecordSet(stringa).
Ma.... questo poteva valere per la mia SELECT (errata).
Perchè le condizioni di ricerca erano solo da aggiungere... in coda (con 
OR).
MA... la tua SELECT, se le categorie sono più di DUE... come dovrei 
ricostruirla?
Intendo dire (e, probabilmente, lo chiedo perchè non ho compreso a fondo 
il funzionamento della tua Select con l'Inner Join)... alla fine della 
tua Select c'è la condizione WHERE, la quale dice "...ove 1c.ID1=1 
e-anche [1C_1].ID=3)".
Quindi... la tua SELECT lavora contemporaneamente con una tabella 
"virtuale" (quella del Inner Join.. AS...) per prelevare UN SOLO dato 
alla volta (comparandolo con quello della tebella NON virtuale).
Secondo questa logica... se le categorie da ricercare sono ENNE... 
dovrei avere... ENNE tabelle virtuali (quelle per INNER JOIN... AS..., 
intendo).
Oppure no?!? :-\
:-)
Mi scuso con te se sono stato un po' criptico (spero tu non abbia già il 
mal di crapa)... Spero di essere riuscito a farmi capire. :-)
Infine... come si fa ad offrirti una birra telematica? :-))
Bye
MioMao

 Grazie :-)
Senti, a questo giro taglio tutto perche' oggi sono un po' stufo di stare 
davanti al PC...e ti passo solo un paio di dritte, poi se al limite non ne 
vieni fuori ti passo il codice pronto.
Avrai Access, immagino.
Ipotizziamo che tu debba cercare per 3 categorie: la 1, la 5 e la 4.
Apri Access.
Crea una query.
Inserisci la tabella MioDB.
Crea la condizione per il caso di id_cat=1, poi infila il codice della query 
in un file di testo.
Poi aggiungi di nuovo la tabella MioDB.
Collega le due tabelle attraverso il campo ID_Des.
Dalla seconda tabella usa il campo ID_cat della nuova tabella per impostare 
id_cat=5
Prendi il codice generato da Access e scrivilo nel solito file di testo.
Aggiungi un'ultima volta la tabella MioDB
Collegala, sempre tramite il campo id_des, alla seconda tabella.
Poi, dalla terza tabella, prendi anche qui il campo id_cat ed impostagli la 
condizione =4
Prendi, anche qui, il codice della query generato automaticamente da Access 
e piazzalo nel solito file di testo.
Ora, se ti ci metti con un po' di pazienza, confrontando le query tra loro 
puoi scrivere un piccolo ciclo che ti costruisce la query che ti serve in 
base al numero di caratteristiche che l'utente sceglie.
Al limite, per non impazzirci piu' del necessario, puoi mettere da parte il 
caso di "una sola condizione" e lavorare solo sulle condizioni multiple.
Poi fai
se numcondizioni=1 allora
    uso una query gia' pronta
altrimenti
    costruisco la query.
Per inciso: ti garantisco che si puo' fare, quel tipo di costruzione l'ho 
fatto gia' diverse volte.
Ciao!

 fatto gia' diverse volte.
Non ne dubito. :-)
Se (domani, dopo domani, oppure dopo domani l'altro... insomma, quando 
ne avrai voglia) puoi passarmi una struttura base per tre "categorie"... 
...mi fai una cortesia (ulteriore). :-)
Poi vedrò di arrangiarmi, senza infierire oltre.
Grazie ancora. :-)
Bye
MioMao

 Grazie ancora. :-)
Figurati, non c'e' problema...se c'e' qualcosa chiedi pure.
(p.s: visto che hai detto che trovare le regole ti piace, sappi che sebbene 
le strutture corrette delle query siano quelle c'e' un piccolo dettaglio che 
non ho inserito e che potrebbe aiutarti a venirne fuori in due secondi... 
;-) )

 che e' sbagliato, ma io preferisco cosi')
Non è che 'tu preferisca così'.
E' proprio che *va fatto così*.
Deve sempre esistere una chiave univoca (anche se in questo caso non 
deve essere indicizzata perchè non serve, anzi, è dannoso che lo sia).
Se ci si basa sulla combinazione delle altre due chiavi, come chiave 
primaria, ci si taglia a priori la possibilità che un domani si possano 
avere informazioni aggiuntive. Ad esempio, potrei scrivere, nella 
medesima tabella, il nome dell'utente che ha creato tale associazione, 
la data di tale evento, utente e data di disassociazione, fatto, 
quest'ultimo, scrivibile con un flag 'Valido' che venga messo a zero. 
Ma poi la stessa identica associazione (formalmente, si chiama 
'relazione') viene ricreata, da un utente diverso in data diversa. 
Avremmo allora due record con le medesime chiavi combinate, ma 
formalmente diversi. E questo è male, molto male.
Aggiungiamo che le due chiavi di relazione, sono in realtà chiavi 
esterne, ossia deve essere posto un vincolo di integrità referenziale, 
ed è bene che le chiavi esterne non siano sottoposte ai controlli di 
integrità delle chiavi esterne.
Poi, in funzione delle ricerche che normalmente si fanno, si studiano 
le opportune indicizzazioni. Ad esempio se spesso si fa un table scan 
cercando 'tutti gli elementi che...', la colonna ID_Categoria sarebbe 
bene che fosse indicizzata Clustered, con abbondante spazio per gli 
inserimenti.
Ciao
Alberto
-- 
A questo punto hanno trovato un muro,
un muro duro, molto molto duro,
che siamo noi.