Access
 sql >> Database >  >> RDS >> Access

In che modo Access comunica con le origini dati ODBC? Parte 2

AGGIORNAMENTO: Aggiunti ulteriori chiarimenti sul significato di SQLExecute e come Access gestisce le query preparate. Grazie, Bob!

Cosa fa Access quando navighiamo e osserviamo i record in una tabella collegata ODBC?

Nella seconda parte della nostra serie di analisi ODBC, la nostra attenzione si focalizzerà sull'impatto che i tipi di recordset hanno all'interno di una tabella collegata ODBC. Nell'ultimo articolo abbiamo imparato come attivare la traccia SQL ODBC e ora possiamo vedere l'output. Se ci hai giocato un po', potresti aver notato che la tua query di Access e le istruzioni SQL ODBC generate da Access non sembrano molto simili. Forniremo anche uno sguardo approfondito su come i tipi influenzano il comportamento delle query SELECT e esamineremo anche diverse varianti di recordset come Snapshot e Dynaset.

Se vuoi seguire, puoi utilizzare il database di esempio fornito qui.

Effetto dei tipi di recordset in una query SELECT

I tipi di recordset influiscono notevolmente sulla modalità di comunicazione di Access con le origini dati ODBC. Potresti aver notato che in una visualizzazione struttura modulo o in visualizzazione struttura query è possibile impostare il tipo di recordset. Per impostazione predefinita, è impostato su Dynaset .

In VBA abbiamo poche altre opzioni, ma per ora non ce ne preoccuperemo. Iniziamo con la comprensione di cosa esattamente Dynaset e Snapshot significa prima. Inizieremo con il tipo meno comunemente usato, Snapshot prima.

Recordset di tipo snapshot

Snapshot è abbastanza semplice. Fondamentalmente significa che prendiamo un'istantanea del risultato al momento dell'esecuzione della query. Normalmente, questo significa anche che Access non può aggiornare il risultato. Tuttavia, esaminiamo come Access interroga l'origine con un recordset basato su snapshot. Possiamo creare una nuova query di Access in questo modo:

L'SQL come possiamo vedere nella vista SQL della query di Access è:

SELECT Cities.*
FROM Cities;
Eseguiremo la query e quindi esamineremo sqlout.txt file. Ecco l'output, formattato per la leggibilità:

SQLExecDirect:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
C'erano poche differenze tra ciò che abbiamo scritto nella query di Access rispetto a ciò che Access ha inviato a ODBC, che analizzeremo.

  1. L'accesso ha qualificato la tabella con il nome dello schema. Ovviamente, nel dialetto Access SQL, non funziona allo stesso modo, ma per il dialetto SQL ODBC, è utile assicurarsi di selezionare dalla tabella giusta. Ciò è regolato da SourceTableName proprietà.
  2. L'accesso ha ampliato i contenuti di Cities.* in un elenco enumerato di tutte le colonne di cui Access è già a conoscenza in base ai Fields raccolta del TableDef sottostante oggetto.
  3. L'accesso ha utilizzato il " per citare gli identificatori, che è ciò che si aspetta il dialetto SQL ODBC. Anche se sia Access SQL che Transact-SQL usano parentesi per citare un identificatore, questa non è una sintassi legale nel dialetto SQL ODBC.

Quindi, anche se abbiamo eseguito solo una semplice query di snapshot selezionando tutte le colonne per una tabella, puoi vedere che Access esegue molte trasformazioni in SQL tra ciò che hai inserito nella visualizzazione della progettazione della query di Access o nella visualizzazione SQL rispetto a ciò che Access effettivamente emette ai dati fonte. In questo caso, tuttavia, è principalmente sintattico, quindi non c'è alcuna reale differenza nell'istruzione SQL tra la query di Access originale e l'istruzione SQL ODBC.

La traccia ha anche aggiunto SQLExecDirect all'inizio dell'istruzione SQL. Torneremo su questo dopo aver esaminato alcuni altri esempi.

Recordset di tipo Dynaset

Utilizzeremo la stessa query, ma riporteremo la proprietà al valore predefinito, Dynaset .
Eseguilo di nuovo e vedremo cosa otteniamo da sqlout.txt . Ancora una volta, è formattato per la leggibilità:

SQLExecDirect:
SELECT
  "Application"."Cities"."CityID"
FROM "Application"."Cities"

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Wow, stanno succedendo un sacco di cose! Questo è decisamente più loquace del recordset di tipo snapshot. Esaminiamoli uno per uno.

Il primo seleziona solo il CityID colonna. Questa è la chiave primaria della tabella, ma soprattutto, è l'indice che Access sta usando dalla sua parte. Ciò diventerà importante quando studieremo le opinioni in seguito. Access utilizza questa query per ottenere le chiavi e utilizzarla per compilare altre query in seguito, come vedremo.

La seconda istruzione è più vicina alla query snapshot originale, tranne per il fatto che ora abbiamo un nuovo WHERE filtraggio delle clausole su CityID colonna. Da ciò possiamo vedere che si tratta di un recupero a riga singola. Possiamo usare le chiavi che abbiamo ottenuto dalla prima query e raccogliere il resto delle colonne in questa query. Ogni volta che l'istruzione preparata viene eseguita, vedrai un SQLExecute: (GOTO BOOKMARK) .

Ma sarebbe inefficiente se dovessimo farlo per tutte le righe... Ed è qui che entra in gioco la query successiva. La terza istruzione è simile alla seconda ma ha 10 predicati. Questa query preparata viene eseguita con ogni SQLExecute: (MULTI_ROW FETCH) . Quindi ciò significa che quando carichiamo un modulo o un foglio dati o addirittura apriamo un recordset nel codice VBA, Access utilizzerà la versione a riga singola o la versione a più righe e compilerà i parametri utilizzando le chiavi ottenute dal primo interrogazione.

Recupero in background e risincronizzazione

Per inciso, hai mai notato come quando apri un modulo o un foglio dati, non vedi la "X di Y" nella barra di navigazione?

Questo perché Access non può sapere quanti ce ne sono finché non ha finito di raccogliere i risultati dalla prima query. Ecco perché spesso potresti scoprire che è molto veloce aprire una query che restituisce una grande quantità di dati. Stai solo visualizzando in anteprima solo una piccola finestra dell'intero recordset mentre Access recupera le righe in background. Se fai clic sul pulsante "Vai all'ultimo", potresti scoprire che blocca l'accesso. Dovresti aspettare che abbia finito di recuperare tutte le chiavi nella prima query prima di poter vedere la "X di Y" nella barra di navigazione.

Quindi, puoi apprezzare come Access possa fornire l'illusione di essere veloce nell'aprire anche un set di record di grandi dimensioni quando utilizziamo un recordset di tipo dynaset e di solito è una buona esperienza per l'utente.

Infine, dobbiamo notare che abbiamo 3 diversi tipi di esecuzioni, SQLExecDirect , SQLPrepare e SQLExecute . Puoi vedere che con il primo non abbiamo parametri. La query è semplicemente così com'è. Tuttavia, se una query deve essere parametrizzata, deve essere prima preparata tramite SQLPrepare e poi eseguito con SQLExecute con i valori per i parametri forniti. Non possiamo vedere quali valori sono stati effettivamente passati in SQLExecute dichiarazione anche se possiamo dedurre da ciò che vediamo in Access. Puoi solo sapere se ha recuperato una singola riga (usando SQLExecute: (GOTO BOOKMARK) o più righe (usando SQLExecute: (MULTI-ROW FETCH) ). Access utilizzerà la versione a più righe per eseguire il recupero in background e riempire il recordset in modo incrementale, ma utilizzerà la versione a riga singola per riempire solo una riga. Questo potrebbe essere il caso in una visualizzazione a modulo singolo anziché in una visualizzazione modulo o foglio dati continua o utilizzarla per risincronizzarsi dopo un aggiornamento.

Navigazione

Con un recordset sufficientemente grande, Access potrebbe non essere in grado di completare il recupero di tutti i record. Come notato in precedenza, all'utente vengono presentati i dati il ​​prima possibile. Normalmente, quando l'utente naviga in avanti attraverso il recordset, Access continuerà a recuperare sempre più record per mantenere il buffer davanti all'utente.

Ma supponiamo che l'utente salti alla centesima riga andando al controllo di navigazione e inserendo 100 lì?

In tal caso, Access presenterà le seguenti domande...

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (GOTO BOOKMARK)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Nota come Access utilizza le istruzioni già preparate che ha creato al momento dell'apertura del recordset. Poiché ha già le chiavi della prima query, è in grado di sapere qual è la "centesima" riga. Per usare un esempio più concreto. Supponiamo di avere CityID a partire da 1, 3, 4, 5…99, 100, 101, 102 senza record per CityID = 2 . Nella prima query, il CityID 101 sarebbe nella centesima riga. Pertanto, quando l'utente passa a 100, Access cerca la centesima riga nella prima query, verifica che sia CityID 101, quindi prende quel valore e lo inserisce in SQLExecute: (GOTO BOOKMARK) per passare immediatamente a quel record. Quindi esamina i successivi 10 record e utilizza i successivi CityID per riempire il buffer con più SQLExecute: (MULTI-ROW FETCH) . Potresti aver notato che c'è un recupero di più righe prima del recupero di una singola riga. Access sta effettivamente recuperando le righe dalla 101a alla 110a nel recupero di più righe e recupera il centesimo record nel successivo recupero di riga singola.

Una volta che Access ha ottenuto i dati per le righe alla centesima, porta l'utente lì, quindi inizia a riempire il buffer attorno a quella centesima riga. Ciò consente all'utente di visualizzare la centesima riga senza dover attendere il caricamento di tutti i record 11-99. L'utente ha anche un'esperienza di navigazione apparentemente veloce quando l'utente fa clic su precedente o successivo dalla nuova posizione perché Access lo ha già caricato in background prima che l'utente lo richiedesse. Questo aiuta a dare l'illusione di essere veloci anche su una rete lenta.

Ma anche se l'utente lascia il modulo aperto e inattivo, Access continuerà a eseguire sia il recupero in background che l'aggiornamento del buffer per evitare di mostrare i dati non aggiornati dell'utente. Ciò è regolato dalle impostazioni ODBC nella finestra di dialogo Opzioni, nella sezione Avanzate nella scheda Impostazioni client:

L'intervallo di aggiornamento ODBC predefinito è 1500 secondi, ma può essere modificato. Può anche essere modificato tramite VBA.

Conclusioni:Chunky o Chatty

Ora dovresti vedere che il motivo principale per cui i recordset di tipo dynaset sono aggiornabili ma i recordset di tipo snapshot non lo sono perché Access è in grado di sostituire una riga nel recordset con la versione più recente dello stesso dal server poiché sa come selezionare un fila unica. Per questo motivo, Access deve gestire 2 query ODBC; uno per recuperare le chiavi e l'altro per recuperare il contenuto effettivo delle righe per una determinata chiave. Tali informazioni non erano presenti con un recordset di tipo snapshot. Abbiamo appena ricevuto una grossa quantità di dati.

Abbiamo esaminato 2 tipi principali di recordset anche se ce ne sono di più. Tuttavia, altri sono solo varianti dei 2 tipi che abbiamo trattato. Ma per ora, è sufficiente ricordare che usare lo snapshot significa essere grosso nella nostra comunicazione di rete. D'altra parte, usare dynaset significa che saremo loquaci. Entrambi hanno i loro alti e bassi.

Ad esempio, il recordset di snapshot non necessita di ulteriori comunicazioni con il server una volta recuperati i dati. Finché il recordset rimane aperto, Access può navigare liberamente nella cache locale. Inoltre, l'accesso non ha bisogno di mantenere alcun blocco e quindi bloccare altri utenti. Tuttavia, un recordset di snapshot è necessariamente più lento da aprire poiché deve raccogliere tutti i dati in anticipo. Può non essere adatto a un recordset di grandi dimensioni, anche se intendi leggere tutti i dati.

Supponiamo che tu stia creando un rapporto di Access di grandi dimensioni di 100 pagine, in genere vale la pena utilizzare recordset di tipo dynaset. Può iniziare a eseguire il rendering dell'anteprima non appena ne ha abbastanza per eseguire il rendering della prima pagina. È meglio che costringerti ad aspettare fino a quando non ha recuperato tutti i dati prima che possa iniziare il rendering dell'anteprima. Sebbene un recordset dynaset possa richiedere blocchi, di solito è per un breve periodo. È sufficiente solo per consentire ad Access di risincronizzare la propria cache locale.

Ma quando pensiamo a quante richieste in più Access invia sulla rete con un recordset di tipo dynaset, è facile vedere che se la latenza della rete è scarsa, le prestazioni di Access ne risentiranno di conseguenza. Affinché Access consenta agli utenti di modificare e aggiornare le origini dati in modo generico, è necessario che Access tenga traccia delle chiavi per selezionare e modificare una singola riga. Lo vedremo nei prossimi articoli. Nel prossimo articolo, vedremo in che modo l'ordinamento e i gruppi influiscono su un recordset di tipo dynaset e come Access determina la chiave da utilizzare per un recordset di tipo dynaset.

Per ulteriore assistenza con Microsoft Access, chiama i nostri esperti al numero 773-809-5456 o inviaci un'e-mail a [email protected].