Come eseguire query con VBA in Access: tutorial pratico

access vba: per eseguire query con VBA in Microsoft Access conviene distinguere tra query di selezione, che restituiscono record, e query di azione, che modificano i dati. Per molte query di azione il metodo CurrentDb.Execute con dbFailOnError è preferibile a DoCmd.OpenQuery, perché evita dipendenza dagli avvisi dell’interfaccia e offre una gestione degli errori più controllabile. Per query parametriche e query di selezione DAO, QueryDef e Recordset sono strumenti fondamentali.

In questa guida vediamo come lanciare query salvate e SQL dinamico, come leggere risultati, passare parametri, usare transazioni, contare record modificati e affrontare i problemi tipici in Access per Microsoft 365, Access 2024 e Runtime.

Indice

  • Query di selezione e query di azione
  • OpenQuery e CurrentDb.Execute
  • QueryDef e parametri
  • Recordset DAO
  • SQL dinamico
  • Transazioni
  • RecordsAffected
  • Error handling
  • Runtime e 32/64 bit
  • SQL Server
  • FAQ

Prima distinzione: leggere o modificare dati

Una query SELECT restituisce un insieme di record. UPDATE, APPEND/INSERT, DELETE e MAKE-TABLE modificano o creano dati. Il modo in cui le esegui da VBA dovrebbe riflettere questa differenza. Se vuoi leggere risultati in codice, apri un Recordset. Se vuoi eseguire una query di azione, usa Execute e verifica l’esito.

Non eseguire una query distruttiva mentre stai ancora verificando la logica. Prima trasformala in una SELECT equivalente e controlla quali record verrebbero coinvolti. Fai un backup quando il rischio è concreto.

DoCmd.OpenQuery: semplice ma legato all’interfaccia

DoCmd.OpenQuery "qryNome" apre o esegue una query salvata. È comodo per interazioni semplici, ma con query di azione può mostrare avvisi di conferma. Alcuni sviluppatori disattivano gli avvisi con DoCmd.SetWarnings False; questa tecnica è rischiosa se un errore impedisce di riattivarli.

Se devi usare SetWarnings, assicurati di ripristinarli in una sezione di uscita eseguita anche in caso di errore. In molti casi è comunque preferibile DAO Execute.

CurrentDb.Execute per query di azione

Esempio:

Public Sub AggiornaStati()
Dim db As DAO.Database
Set db = CurrentDb
db.Execute "UPDATE Ordini SET Stato='Scaduto' WHERE DataScadenza < Date() AND Stato<>'Pagato';", dbFailOnError
MsgBox db.RecordsAffected & " record aggiornati."
Set db = Nothing
End Sub

dbFailOnError fa sì che DAO generi errore quando l’operazione non riesce. RecordsAffected consente di sapere quanti record sono stati modificati.

Eseguire una query salvata con Execute

Puoi eseguire una QueryDef salvata:

CurrentDb.QueryDefs("qryAggiornaStati").Execute dbFailOnError

Se vuoi leggere RecordsAffected devi mantenere il riferimento alla QueryDef:

Dim qd As DAO.QueryDef
Set qd = CurrentDb.QueryDefs("qryAggiornaStati")
qd.Execute dbFailOnError
Debug.Print qd.RecordsAffected

Query parametriche con QueryDef

Il QueryDef è particolarmente utile per evitare concatenazioni fragili. Supponiamo di avere:

PARAMETERS pDataInizio DateTime, pDataFine DateTime;
SELECT * FROM Ordini WHERE DataOrdine Between [pDataInizio] And [pDataFine];

In VBA:

Dim qd As DAO.QueryDef
Dim rs As DAO.Recordset
Set qd = CurrentDb.QueryDefs("qryOrdiniPeriodo")
qd.Parameters("pDataInizio") = DateSerial(2026, 8, 1)
qd.Parameters("pDataFine") = DateSerial(2026, 8, 31)
Set rs = qd.OpenRecordset(dbOpenSnapshot)

I parametri tipizzati evitano molti problemi di formato data e quoting.

Aprire un Recordset di selezione

Per leggere i risultati:

Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset("SELECT IDCliente, Nome FROM Clienti ORDER BY Nome;", dbOpenSnapshot)
Do While Not rs.EOF
Debug.Print rs!IDCliente, rs!Nome
rs.MoveNext
Loop
rs.Close
Set rs = Nothing

Usa dbOpenSnapshot se devi soltanto leggere. Un dynaset è appropriato quando devi modificare record attraverso il recordset.

SQL dinamico: quando serve

È utile quando tabelle, campi o parti della logica cambiano in base al contesto. Evita però di concatenare input utente direttamente in SQL. Per valori, preferisci parametri; per nomi di oggetti, valida contro un insieme atteso.

Se concatenare testo è inevitabile, raddoppia gli apostrofi con Replace(valore, "'", "''"). Per le date usa parametri tipizzati ogni volta che puoi.

Debug.Print per SQL dinamico

Prima di eseguire una stringa complessa, stampa Debug.Print sql. Copiala nella visualizzazione SQL di una query e verifica. Questa tecnica trova rapidamente spazi mancanti, virgolette errate e nomi campo sbagliati.

Query di aggiornamento sicure

Un UPDATE senza WHERE può modificare l’intera tabella. Costruisci quindi la query in due fasi: prima una SELECT con lo stesso WHERE, poi l’UPDATE. Se il numero di record previsto è limitato, puoi aggiungere un controllo di conteggio e interrompere se supera una soglia.

Esempio: se ti aspetti al massimo 500 record e la query ne coinvolge 50.000, blocca l’esecuzione e richiedi verifica.

DELETE: precauzioni

Le query DELETE devono avere backup e criteri verificati. Non usare cancellazioni permanenti se il requisito può essere soddisfatto con un campo Stato o una tabella archivio. Nei sistemi aziendali la tracciabilità può essere più importante del risparmio di spazio.

Append e duplicati

Quando esegui INSERT/APPEND, la chiave univoca deve impedire duplicati. Se l’import può essere ripetuto, rendi il processo idempotente usando chiavi business, ID batch o query che inseriscono solo record mancanti.

Transazioni DAO

Se più query devono riuscire tutte insieme, usa una transazione sul Workspace DAO. Concettualmente: BeginTrans, esegui query, CommitTrans; in caso di errore Rollback. Questo evita di lasciare metà aggiornamento completato.

Le transazioni richiedono attenzione: non mantenerle aperte più del necessario e considera i lock in ambiente multiutente.

Query su tabelle collegate

Execute funziona anche su molte tabelle collegate, ma prestazioni e capacità dipendono dalla sorgente. Su SQL Server, una query Access può essere tradotta via ODBC o elaborata parzialmente localmente. Per operazioni pesanti valuta pass-through o stored procedure sul server.

Pass-through query

Una pass-through invia SQL direttamente al server ODBC. È utile per sfruttare T-SQL, stored procedure e processing server-side. Non usa la sintassi Access SQL per il contenuto SQL. Imposta Connect e ReturnsRecords in base all’operazione.

Con dati sensibili evita password hard-coded nella stringa ODBC. Usa autenticazione e configurazioni appropriate.

Query non aggiornabile

Se un recordset basato su una query non è aggiornabile, la causa può essere join, aggregazioni, DISTINCT, union o sorgenti particolari. Non cercare di forzare l’aggiornamento via VBA senza capire il motivo. Modifica la query o esegui un UPDATE mirato sulla tabella corretta.

Gestire parametri di maschera

Una query salvata può riferirsi a Forms!frmFiltro!txtData. Funziona se la maschera è aperta, ma rende la query dipendente dalla UI. Per procedure riutilizzabili e batch, parametri espliciti QueryDef sono più robusti.

Query e Access Runtime

Runtime può eseguire query da VBA. Evita però procedure che richiedono all’utente di aprire query in struttura o correggere parametri manualmente. L’app deve gestire input tramite maschere e messaggi chiari.

32 bit e 64 bit

DAO e il normale SQL Access funzionano in entrambe le architetture Office. I problemi emergono se il progetto usa provider o driver esterni. In SQL Server verifica il driver ODBC installato nella bitness corretta.

Microsoft 365 e Access 2024

Le tecniche DAO e DoCmd descritte sono proprie di Access desktop moderno. Microsoft Learn mantiene il riferimento del modello a oggetti Access e DAO. Prima di usare proprietà specifiche verifica la documentazione corrente.

Gestione errori

Schema:

On Error GoTo GestioneErrore
' esecuzione query
Uscita:
Exit Sub
GestioneErrore:
MsgBox "Errore " & Err.Number & ": " & Err.Description
Resume Uscita

In produzione registra anche il nome query e i parametri, ma non dati sensibili inutili.

Controllare RecordsAffected

Dopo un UPDATE o DELETE verifica il numero di record. Se zero può significare che il filtro non ha trovato corrispondenze; se enorme può indicare un WHERE errato. Trasforma questo numero in una metrica di sicurezza.

Ottimizzare le prestazioni

Evita di eseguire una query per ogni riga quando una singola query set-based può fare il lavoro. Indici sui campi usati nei criteri e join possono migliorare notevolmente le prestazioni. Su tabelle collegate, riduci i dati trasferiti.

Problemi comuni

Troppi parametri previsti

Spesso un nome campo è scritto male o un riferimento Forms non viene risolto.

Tipo dati non corrispondente

Controlla tipi parametri e valori Null. Dichiarare PARAMETERS nella query aiuta.

Query non aggiornabile

Rivedi struttura e sorgenti. Non tutte le SELECT permettono modifiche.

Avvisi disattivati

Se hai usato SetWarnings False, assicurati di riattivarli in uscita.

Prestazioni lente

Controlla indici, funzioni nei criteri, join e quantità di dati trasferiti dalla rete.

Checklist

Classifica la query, prova come SELECT, verifica WHERE, usa dbFailOnError, parametri tipizzati, RecordsAffected, transazioni quando necessarie e log. Testa zero record, molti record, Null, rete non disponibile e permessi insufficienti.

Per query critiche crea casi di test ripetibili e mantieni una copia di backup. In multiutente limita la durata delle transazioni e osserva eventuali lock.

FAQ

OpenQuery o Execute?

OpenQuery è comodo per interfaccia e query visibili; Execute è spesso preferibile per query di azione controllate da codice.

Come leggo i risultati di una SELECT?

Apri un DAO.Recordset, preferibilmente snapshot se devi solo leggere.

Come passo date senza errori?

Usa QueryDef con parametri DateTime.

Come so quanti record sono stati aggiornati?

Leggi RecordsAffected sull’oggetto Database o QueryDef che ha eseguito la query.

Posso usare transazioni?

Sì, DAO Workspace supporta transazioni. Usale per gruppi di modifiche che devono essere atomiche.

Approfondimenti

Conclusione

Eseguire query con VBA in Access è affidabile quando separi lettura e modifica, usi parametri tipizzati, controlli RecordsAffected e gestisci gli errori. Per query di azione privilegia Execute con dbFailOnError; per letture usa Recordset; per parametri usa QueryDef. Aggiungi transazioni quando più modifiche devono riuscire insieme e considera pass-through per carichi SQL Server. Questo approccio rende le automazioni più prevedibili, sicure e performanti.

Lascia un commento