PROGRAMMO SUBITO n.14 - Corso di Visual Basic

 

Questo mese il corso dedicato a Visual Basic da nuovamente spazio ai database. Oggetto di studio sono infatti le modalità che permettono di interrogare una struttura per mezzo del linguaggio SQL

Corso di Visual Basic
Come interrogare i database
(Parte 14)

di Maurizio Crespi

Spesso si sente parlare dei database come di strutture che devono essere "interrogate", ovvero di oggetti pressoché attivi in grado di restituire delle informazioni a comando. In realtà ciò che è attivo non è il database vero e proprio, bensì il motore che lo gestisce. In questa lezione saranno descritte le modalità con cui è possibile richiedere al modulo responsabile della gestione degli archivi di effettuare delle ricerche e di fornire dei dati organizzati secondo una struttura differente da quella con cui essi sono memorizzati sul disco.

La soluzione dell'esercizio proposto nella scorsa lezione

Come sempre, prima di introdurre i nuovi argomenti, sarà presentata la soluzione dell'esercizio proposto nella scorsa lezione. Nello numero precedente, è stato descritto un programma in grado di gestire una semplice rubrica telefonica. L'esercizio ne prevede la modifica con l'aggiunta di un pulsante in grado di contare gli elementi dell'archivio contenenti nel campo Cognome una sequenza di caratteri indicata dall'utente. Supponendo di assegnare al nuovo tasto il nome btnConta, il codice che deve essere associato alla sua pressione è il seguente:

Private Sub btnConta_Click()
Dim Criterio As String
Dim Contatore As Integer

Contatore = 0
Criterio = "Cognome LIKE ""*" & txtCerca.Text & "*"""
dbArchivio.Recordset.FindFirst (Criterio)
Do While Not dbArchivio.Recordset.NoMatch
Contatore = Contatore + 1
dbArchivio.Recordset.FindNext (Criterio)
Loop
MsgBox "Sono stati trovati " & Contatore & " record"
End Sub

Per leggere la stringa da cercare si fa uso della casella di testo txtCerca, già presente nell'applicazione in quanto usata dal codice associato alla pressione del tasto di ricerca (btnCerca). Si noti il criterio di selezione, basato sull'operatore LIKE. Per fare in modo che siano trovati tutti i record che contengano la scritta inserita dall'utente in una qualsiasi posizione, occorre introdurre prima e dopo la sequenza da cercare il carattere jolly *. La stringa che costituisce il criterio di ricerca, supponendo di aver digitato nella casella txtCerca la sequenza "Dev", è la seguente:

Cognome LIKE "*Dev*"

L'asterisco è in grado di sostituire un numero variabile di caratteri. Ciò significa che sono considerate rispondenti al criterio tutte le stringhe costituite da una sequenza qualsiasi, eventualmente nulla, seguita dalla parola "Dev" e da un'altra sequenza qualsiasi, anch'essa eventualmente nulla.
Per mezzo del metodo FindFirst dell'oggetto Recordset associato all'archivio, è ricercato il primo record che soddisfa il criterio. Un ciclo, che si interrompe solo quando la proprietà NoMatch diventa positiva, ovvero quando non sono più trovati elementi corrispondenti ai parametri di ricerca indicati, fa sì che sia più volte invocato il metodo FindNext, che provoca la lettura del successivo elemento soddisfacente i criteri. Il codice dell'applicazione completa è riportato nel listato 1.

Cosa significa "interrogare un database"

Un'applicazione che fa uso di un database percepisce tale struttura come attiva, cioè in grado di rispondere a delle richieste. Il programmatore può infatti creare diverse viste dell'archivio, scegliendo solo i campi desiderati e ordinando i record secondo le proprie preferenze. La creazione di una vista non cambia la conformazione fisica del database, bensì comporta la generazione di una struttura logica personalizzata che permette all'applicazione che accede all'archivio di avere di esso una visione adeguata alle proprie esigenze. Una struttura logica di questo tipo prende il nome di dynaset (abbreviazione di dynamic set, ovvero insieme dinamico) e l'operazione che porta alla sua creazione è in genere detta interrogazione del database.

e query

Un termine che si usa spesso quando si parla di database è costituito dalla parola query. Una query non è altro che un'interrogazione del database, ovvero l'estrazione da esso dell'insieme costituito dai dati in grado di soddisfare delle condizioni specificate. Una query quindi rappresenta un'operazione effettuata sull'archivio secondo delle modalità ben precise, che sono descritte tipicamente per mezzo di una stringa contenente un testo composto da nomi di elementi del database correlati per mezzo di parole chiave appartenenti ad un linguaggio particolare (esso è detto in genere linguaggio di interrogazione o, dagli amanti della lingua inglese, query language). Sulla scena esistono molti linguaggi di questo tipo. In passato, infatti, ogni motore di database tendeva a possedere un proprio linguaggio di interrogazione proprietario. Col passare del tempo, tuttavia, l'esigenza di creare uno standard che permettesse di operare con prodotti diversi riducendo al minimo i costosi corsi di formazione si è sempre più fatta sentire. I moderni strumenti, quindi, sono andati via via adeguandosi alle richieste dell'utenza e oggi, sebbene sopravvivano ancora molti linguaggi proprietari, si può affermare che lo standard mondiale, almeno per alcune categorie di prodotti, sia costituito dallo Structured Query Language (linguaggio strutturato di interrogazione), il cui nome è noto ai più sotto forma di sigla (SQL). I vantaggi principali offerti da questo linguaggio sono rappresentati dalla semplicità, dalla notevole potenza e dalla portabilità da uno strumento di gestione dei database a un altro. Quest'ultima caratteristica non è tuttavia valida al 100%, in quanto spesso si possono osservare delle piccole variazioni fra i linguaggi previsti dai vari prodotti.

Il linguaggio SQL

Il linguaggio SQL rappresenta uno standard per tutti i recenti prodotti Microsoft in grado di accedere a dei database. Anche il motore di gestione degli archivi integrato in Visual Basic non si sottrae questa regola.
Per mezzo di una stringa SQL è quindi possibile definire la struttura logica, i requisiti, nonché l'ordinamento dei record che devono essere utilizzati da un controllo di tipo data.
L'istruzione SQL di più frequente utilizzo è denominata SELECT. La sua sintassi è la seguente:

SELECT <elenco_campi>;
FROM <tabella>
dove <elenco_campi> ha la sintassi:
<campo_1>[,<campo_2>,, <campo_n>]

Per mezzo dell'istruzione SELECT è possibile specificare un elenco di campi che costituisce la struttura logica da attribuire ai record da prelevare dal database. La tabella in cui essi sono contenuti è specificata dopo la clausola FROM.
Ad esempio, si supponga di disporre di un database denominato VeicoliAziendali, in cui ciascun record contiene tutte le informazioni riguardati un veicolo aziendale. All'atto dell'acquisto di una nuova automobile, in archivio sono inserite tutte le informazioni atte a identificarla in modo preciso. Il database deve pertanto prevedere una tabella, che si supporrà denominata Automobili, in cui sono presenti dei campi in grado di ospitare la marca, il modello, la versione, il numero di telaio, la targa, il numero del contratto di assicurazione, la data di immatricolazione, ecc.
Si supponga di voler realizzare un'applicazione che consenta al responsabile della gestione del parco veicoli di verificare quali autovetture hanno superato i 5 anni di età e necessitano quindi di essere sostituite. È evidente che un'applicazione di questo tipo necessita per ogni veicolo delle informazioni relative all'anno di immatricolazione, al numero identificativo attribuito dall'azienda e al nominativo della persona a cui è stato affidato. Sicuramente non risulta utile conoscere il colore del l'auto, né il numero di telaio o la scadenza del contratto di assicurazione. Per fare in modo che sia caricata in memoria una minore quantità di informazioni, rendendo meno gravoso il compito del sistema e agevolando le operazioni di debug al programmatore, è possibile fare in modo che il controllo di tipo data preposto alla lettura delle informazioni abbia una percezione dell'archivio diversa da quella reale, ovvero sia in grado di leggere dei record composti dai soli campi necessari. Ciò è possibile provvedendo a fornire all'oggetto la stringa SQL:

SELECT Anno, Numero, Utente;
FROM Automobili

Tale sequenza fa sì che il modulo di accesso ai dati provveda a creare un recordset composto da record caratterizzati dalla presenza dei soli 3 campi Anno, Numero, Utente. I dati sono prelevati dalla tabella Automobili. L'applicazione può eseguire qualsiasi operazione sugli elementi del dynaset, ivi compresa la modifica dei contenuti o la loro cancellazione. Naturalmente, le informazioni poste nella tabella di provenienza sono costantemente mantenute sincronizzate con quelle presenti nel dynaset, per cui ogni operazione effettuata sulla struttura logica influenza l'archivio memorizzato fisicamente sul disco.
Per poter rendere ancora più veloce l'applicazione e per semplificare ulteriormente il compito del programmatore, sarebbe senz'altro utile disporre di un archivio costituito esclusivamente dai record che descrivono i veicoli che hanno almeno 5 anni. In tal modo, non sarebbero necessari altri controlli sui dati e il programma dovrebbe semplicemente limitarsi a visualizzare sequenzialmente tutti gli elementi forniti dal motore di gestione del database. Per mezzo della clausola WHERE, da utilizzare in combinazione con l'istruzione SELECT, è possibile fare in modo che il programma veda i dati relativi ai veicoli più anziani come contenuti all'interno di una tabella ad hoc, sebbene in realtà siano posti nella stessa struttura che contiene le informazioni relative alle altre vetture. La sintassi è la seguente:

SELECT <elenco_campi>;
FROM
<tabella>;
WHERE
<condizione>

dove <condizione> rappresenta un'espressione di confronto valida, definita secondo lo schema

<confronto> [And|Or <confronto>… And|Or <confonto>]

<confronto> è definito come

<campo> =|<>|<|>|<=|>=|Like [<valore>|<campo>]

oppure

<campo> Between <valore> And <valore>

L'uso della clausola WHERE implica la presenza di un criterio di scelta, che è descritto da una o più condizioni combinate per mezzo dei canonici operatori logici. Si noti che oltre ai tipici operatori di confronto è possibile utilizzare la parola Between per verificare l'appartenenza del contenuto di un campo a un preciso intervallo di valori.
Ad esempio, volendo estrarre dall'archivio delle vetture aziendali tutti i veicoli immatricolati prima del 1995, è necessario effettuare una query descritta dalla stringa

SELECT Anno, Numero, Utente;
FROM Automobili;
WHERE Anno<1995

I campi indicati nei criteri di selezione non devono necessariamente essere menzionati anche dopo il comando SELECT. Nel caso della query

SELECT Anno, Numero, Utente;
FROM Automobili;
WHERE (Anno<1995) And (Tipo='Station Wagon')


non ha alcun senso prelevare il campo Tipo dall'archivio, in quanto la condizione indicata fa sì che possa solo essere costituito dalla stringa "Station Wagon".Osservando la frase SQL appena descritta, si può notare che il criterio di scelta è costituito da due condizioni racchiuse fra parentesi e combinate per mezzo dell'operatore logico And. L'uso delle parentesi, sebbene spesso non sia obbligatorio, risulta consigliabile in presenza delle parole chiave And e Or al fine di favorire la leggibilità de codice. Inoltre, la stringa alfanumerica da confrontare con il contenuto del campo Tipo è racchiusa fra apici. In alcuni casi, ad esempio in presenza di frasi contenenti degli apostrofi, può rivelarsi necessario l'utilizzo di un diverso delimitatore per le stringhe. L'alternativa è costituita dall'uso delle virgolette (").

La selezione di tutti i campi

Talvolta si rivela necessario utilizzare una query per leggere tutti i record che soddisfano una condizione senza che sia necessario variare la loro struttura logica, ovvero rendendo disponibili all'applicazione tutti i campi che li compongono. In questi casi, può risultare scomodo dover fornire l'elenco completo dei campi dopo la parola SELECT, soprattutto se il loro numero è elevato. È allora possibile utilizzare il carattere *, che significa tutti i campi.

La stringa
SELECT *;
FROM Automobili;
WHERE Anno<1995

crea pertanto una query che provvede a prelevare dal database tutti i campi di tutti i record presenti nella tabella Automobili che sono caratterizzati dal contenere un valore inferiore a 1995 nel campo Anno.

Un esempio…

Si supponga di voler realizzare un'applicazione in grado di estrarre da un archivio di auto aziendali, contenuto in una tabella denominata Automobili, l'elenco dei veicoli immatricolati nell'anno 1998. Si supponga che nell'archivio esistano almeno i campi Anno, Targa, Modello, Sede, contenenti rispettivamente le informazioni riguardanti l'anno di immatricolazione, la targa, il modello e la sede alla quale il veicolo è stato assegnato.
Come sempre, il primo passo da compiere riguarda la creazione di un form, in cui è necessario inserire un oggetto di tipo data, utilizzato per leggere le informazioni contenute nel database e quattro etichette, destinate ad accogliere i dati contenuti nei campi. Come per tutte le altre applicazioni facenti uso dei database, occorre collegare l'oggetto di tipo data, a cui sarà dato il nome Query, all'archivio. Il passo successivo consiste nel collegare all'elemento Query le etichette testuali usate per visualizzare il contenuto dei campi Anno, Targa, Modello e Sede. Si agisce quindi come se si volesse realizzare un'applicazione in grado di leggere sequenzialmente tutti i record dell'archivio. La differenza rispetto a un programma di questo tipo consiste esclusivamente nel valore assunto dalle proprietà RecordsetType e RecordSource dell'oggetto di tipo Data. La prima deve essere impostata al valore Dynaset in luogo di Table (tabella), mentre la seconda, anziché contenere il nome della tabella da cui devono essere prelevati i dati, deve ospitare la stringa SQL che descrive la query da effettuare, ovvero:

SELECT Anno, Targa, Modello, Sede;
FROM Automobili;
WHERE Anno=1998

Conclusioni

La possibilità di eseguire su un archivio locale o remoto delle query descritte da stringhe in linguaggio SQL fa di Visual Basic uno strumento particolarmente indicato per gestire i database. Non è quindi un caso che il prodotto Microsoft si stia sempre più affermando come uno degli strumenti standard per la realizzazione di software gestionale in ambiente Windows. Data l'importanza dell'argomento, anche la prossima lezione di questo corso sarà dedicata alla realizzazione e alla gestione delle query. Per saperne di più, al lettore non resta che attendere il prossimo numero…

Bibliografia

"Visual Basic 5", McGrawHill, ISBN 88-386-0436-3

Maurizio Crespi si occupa di grafica, multimedialità, amministrazione di reti locali e geografiche, nonché della progettazione e dello sviluppo di applicazioni in C++, Visual Basic, Delphi e Director. Può essere contattato tramite Internet all'indirizzo mcrespi@infomedia.it.

VB-IT: per tutti gli sviluppatori VB o aspiranti tali

VB-IT e' la mailing list italiana interamente dedicata a Visual Basic, VBA (Visual Basic for Application) e VBScript. Se sei uno sviluppatore esperto oppure ti interessa il mondo Visual Basic anche solo per diletto, troverai VB-IT utilissima!
Consigli, suggerimenti, trucchi, soluzioni a problemi comuni e molto altro. Per iscriversi, gratuitamente, a VB-IT è sufficiente inviare un messaggio a majordomo@infomedia.it e nel body inserire la stringa: subscribe vb-it
Una volta iscritto, esponi i tuoi problemi a vb-it@infomedia.it e aiuta gli altri a risolvere i propri. Sarà anche un modo per instaurare nuovi rapporti di lavoro, collaborazione ed amicizia!