ADO Parameters versione 2.0
Inizialmente volevo dedicare questa parte alla SELECT, ma in effetti mi sono reso conto che sarà sufficiente leggere il codice per capire come comporre una SELECT.
In particolare suggerisco di studiarsi bene la nuova routine RecordRicercaAvanzata del modulo frmEditRecord che è può essere molto utile per comprenderne l'uso, abbinata come sempre all'uso dei parametri di ADO.
Le novità di questa seconda parte sono molte. Nel file guida.txt troverete tutte le informazioni utili e raccomando di leggerlo. Ecco l'elenco delle novità principali:
- aggiunto il menu
- gestione pulsanti migliorata
- aggiunta la Ricerca Avanzata: consente ricerca su tutti i campi!
- migliorata la gestione delle finestre
- altri piccoli miglioramenti di poco conto
- ecc...
Ma la novità più importante è rappresentata da un gruppo di routine che consente di impostare i parametri di ADO in maniera straordinariamente semplice. Le ho riunite tutte in un modulo modADO.bas e sono:
- SetADOParameter
- RicavaTipoCampo
- RicavaDefinedSize
- ImpostaMaxLengthTextBox
Vediamone le firme:
Public Sub SetADOParameter(ByRef cmd As ADODB.Command, ByVal sTableName As String, _
ByVal sFieldName As String, ByVal parValue As Variant)
Public Function RicavaTipoCampo(ByVal sTableName As String, ByVal sFieldName As String) As ADODB.DataTypeEnum
Public Function RicavaDefinedSize(ByVal sTableName As String, ByVal sFieldName As String) As Long
Public Sub ImpostaMaxLengthTextBox(ByRef f As Form, ByVal sTableName As String)
In pratica, invece di creare manualmente tutti i parametri utilizzando i metodi dell'oggetto Command CreateParameter e Parameters.Append come facevamo prima:
Set par = cmd.CreateParameter("@cognome", adVarChar, adParamInput, 50, txtCognome.Text)
cmd.Parameters.Append par
ora potremo indicare più semplicemente:
SetADOParameter cmd, sTabella, "cognome", txtCognome.Text
La cosa che ritengo molto utile è, come potete vedere, che la nuova routine SetADOParameter oltre ad essere molto più semplice da scrivere (una sola riga di codice), non sarà più necessario indicare :
1 - il tipo di dato
2 - la direzione del parametro (*)
3 - la dimensione del campo (per i campi di tipo testo)
Questo perchè SetADOParameter pensa a fare tutto questo lavoro al posto nostro, grazie proprio alle altre quattro routine elencato sopra.
Il vantaggio non sta tanto nello scrivere una riga di codice anzichè due, ma nel fatto che non dovremo più andare a controllare nel database i valori necessari (vedi sopra 1, 2 e 3) il che francamente è la vare scocciatura.
Se poi, in futuro, cambiamo il tipo oppure la dimensione del campo saremmo costretti a rivedere tutte le impostazioni del relativo parametro.
Invece grazie a SetADOParameter il codice non sarà assolutamente da toccare, almeno non per quanto riguarda la creazione del parametro, e non è un risparmio da poco.
(*) E' ovvio che sarà usato sempre adParamInput, che in Access è l'unica direzione possibile, ma siete liberi di parametrizzare ulteriormente la routine indicandone la direzione qualora utilizzate database che la supportano.
Ora voglio parlare brevemente delle date
Nella prima versione del progetto abbiamo visto in dettaglio come eseguire azioni importanti come INSERT e UPDATE, ma non abbiamo ancora esaminato nel dettaglio come si imposta una SELECT.
E' pur vero che nella routine 'QueryOggiAdHoc' del modulo 'frmQuery' abbiamo utilizzato una SELECT, ma questo serviva più che altro a confrontare i due tipi di query (stored procedure e ad hoc), e l'uso era limitatamente riferito ad una selezione di intervallo di date.
Se ritenete di sapere già tutto sulle date e sul come gestirle correttamente, potete saltare questa parte.
----------------------------------------------------------------------
LE DATE: non tutte le ciambelle riescono col buco
----------------------------------------------------------------------
A tal proposito è utile soffermarci un attimo sulla questione date perchè sicuramente avrete notato come ho impostato i parametri nel definire l'intervallo di date DA... A...
Soprattutto credo che più di qualcuno si sia chiesto il perchè nel parametro A... sia stato aggiunto la parte 'ora' alla data utilizzando la stringa
23.59.59
Questo aspetto della questione sulle date è molto importante perchè spesso crea in chi non ha molta esperienza sui database una sensazione mista tra delusione ed impotenza. Veniamo al sodo.
Quando si esegue un'interrogazione del tipo:
'Dammi l'elenco di tutti gli ordini stipulati tra il 1 gennaio ed il 20 marzo'
viene logico pensare che la query debba essere costruita così:
SELECT NumeroOrdine, DataOrdine
FROM Ordini
WHERE DataOrdine BETWEEN #01/01/2008# AND #20/03/2008#
N.B. Per semplificare la comprensione dell'argomento, sto indicano le date nel formato italiano.
Ma tenete sempre presente che nella stragrande maggioranza dei database il formato della data di default è smpre quello americano MM/DD/YYYY HH:NN:SS (se non impostato in modo diverso).
Purtroppo in un database MDB (Access) non abbiamo scampo perchè non è possibile impostare il formato dei campi Date/Time, che sarà sempre e solo americano.
Non tutti conoscono questo 'dettaglio' perchè aprendo una tabella di un database in ambiente MsAccess le data sono visualizzate nel formato italiano DD/MM/YYYY HH:NN:SS ed è facile cadere nel tranello credendo che anche nel codice VB6 vanno indicate così.
Ma così non è! MsAccess usa il formato di visualizzazione indicato nelle impostazioni regionali del sistema, quindi se abbiamo Windows in italiano, userà il formato italiano.
Ciò nonostrante, il formato del tipo Date/Time internamente resta sempre l'americano, e da codice VB6 'deve' sempre essere formattato usando l'apposita funzione Format().
In realtà, usando i parametri di ADO, questo problema non si pone, dato che pensa lui a tutto.
Una volta eseguita la query, se andiamo a fare una verifica (spero che tutti la facciano!) scopriamo che mancano tutti gli ordini relativi all'ultimo giorno (e qui inizia lo sconcerto!).
La causa di questo è perchè non si è considerato la parte ORA pensando che la parte DATA è sufficiente.
Perchè? La risposta è semplice però non voglio fornirvela come un assunto, ma vi aiuterò ad arrivarci da soli.
Quando voi indicate l'intervallo iniziale #01/01/2008# il database in realtà interpreta questo:
#01/01/2008 0.00.00#
Perchè è ovvio che il giorno inizia dallo ore 0.00.00. Vero?
Ma così è altrettanto ovvio che un giorno termina alle 23.59.59.
Ora, se come intervallo finale voi indicate #20/03/2008# come lo interpreta il database? In base a quanto abbiamo appena capito, lo interpreterà così:
#20/03/2008 0.00.00#
Ecco perchè gli ordini dell'ultimo giorno non saranno mai inclusi nel risultato della query, semplicemente perchè avete escluso quelli stipulati dal #20/03/2008 0.00.00# al #20/03/2008 23.59.59#.
Indicando l'intervallo BETWEEN #01/01/2008# AND #20/03/2008# in realtà equivale a scrivere
BETWEEN #01/01/2008 0.00.00# AND #19/03/2008 23.59.59#
perchè dovrebbe proprio essere un caso che un ordina sia stato stipulato alle ore 0.00.00 del 20/03/2008, non trovate?
----------------------------------------------------------------------
SOLUZIONE
----------------------------------------------------------------------
Esistono due tipi di soluzioni a questo problema:
1) Includere nella proposizione WHERE anche la parte ORA, così
WHERE DataOrdine BETWEEN #01/01/2008# AND #20/03/2008 23.59.59#
2) Chiedere al database di confrontare solo parte DATA, così
WHERE Format(DataOrdine, 'MM/DD/YYYY') BETWEEN #01/01/2008# AND #20/03/2008#
Ricordare che, se non espressamente indicato, il motore del database considerare sempre il valore completo, esattamente come avviene per tutti gli altri campi.
Spero di aver fornito sufficienti informazioni affinchè sia possibile utilizzare in maniera soddisfacente i parametri di ADO ricordando che tali informazioni saranno utili ancor di più quando realizzerete applicazioni con i linguaggi .NET.
Saluti