sql >> Databasteknik >  >> RDS >> Access

Hur pratar Access med ODBC-datakällor? Del 2

UPPDATERING: Lade till ytterligare några förtydliganden kring innebörden av SQLExecute och hur Access hanterar de förberedda frågorna. Tack, Bob!

Vad gör Access när vi bläddrar och tittar på poster i en ODBC-länkad tabell?

I den andra delen av vår ODBC-spårningsserie kommer vårt fokus att vända sig till den inverkan postuppsättningstyperna har inom en ODBC-länkad tabell. I den senaste artikeln lärde vi oss hur man aktiverar ODBC SQL-spårning och vi kan nu se utdata. Om du har lekt med det lite, kanske du har märkt att din Access-fråga och ODBC SQL-satserna som Access genererar inte ser särskilt lika ut. Vi kommer också att ge en djupgående titt på hur typerna påverkar beteendet hos SELECT-frågor, och vi kommer också att undersöka olika varianter av postuppsättningar som Snapshots och Dynasets.

Om du vill följa med kan du använda exempeldatabasen som finns här.

Effekt av postuppsättningstyper i en SELECT-fråga

Recordset-typerna har stor effekt på hur Access kommer att kommunicera med ODBC-datakällorna. Du kanske har märkt att du i en formulärdesignvy eller i frågedesignvy kan ställa in postuppsättningstypen. Som standard är den inställd på Dynaset .

I VBA har vi några fler alternativ men vi kommer inte att oroa oss för det för tillfället. Låt oss börja med att förstå exakt vad Dynaset och Snapshot betyder först. Vi börjar med mindre vanligt förekommande typ, Snapshot först.

Recorduppsättningar av ögonblicksbild

Snapshot är ganska enkelt. Det betyder i princip att vi tar en ögonblicksbild av resultatet vid tidpunkten för frågans körning. Normalt innebär detta också att Access inte kan uppdatera resultatet. Men låt oss titta på hur Access frågar källan med en ögonblicksbildbaserad postuppsättning. Vi kan skapa en ny Access-fråga så här:

SQL som vi kan se i Access-frågans SQL-vy är:

SELECT Cities.*
FROM Cities;
Vi kör frågan och tittar sedan på sqlout.txt fil. Här är utdata, formaterad för läsbarhet:

SQLExecDirect:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
Det var få skillnader mellan det vi skrev i Access’ fråga jämfört med det som Access skickade till ODBC, som vi kommer att analysera.

  1. Åtkomst kvalificerade tabellen med schemanamnet. Uppenbarligen, i Access SQL-dialekt, fungerar det inte på samma sätt, men för ODBC SQL-dialekt är det bra att se till att vi väljer från rätt tabell. Det styrs av SourceTableName egendom.
  2. Åtkomst utökade innehållet i Cities.* i en uppräknad lista över alla kolumner som Access redan känner till baserat på Fields samling av den underliggande TableDef objekt.
  3. Åtkomst använde " för att citera identifierarna, vilket är vad ODBC SQL-dialekten förväntar sig. Även om både Access SQL och Transact-SQL använder parenteser för att citera en identifierare, är det inte en laglig syntax i ODBC SQL-dialekten.

Så även om vi bara gjorde en enkel ögonblicksbildsfråga genom att välja alla kolumner för en tabell, kan du se att Access gör en hel del transformation till SQL mellan vad du lägger i Access-frågedesignvyn eller SQL-vyn kontra vad Access faktiskt avger till data källa. I det här fallet är det dock mestadels syntaktisk så det finns ingen verklig skillnad i SQL-satsen mellan den ursprungliga Access-frågan och ODBC SQL-satsen.

Spåret lade också till SQLExecDirect i början av SQL-satsen. Vi återkommer till det när vi har tittat på några andra exempel.

Dynaset-postuppsättningar

Vi använder samma fråga men ändrar egenskapen tillbaka till dess standard, Dynaset .
Kör det igen, så ser vi vad vi får ut av sqlout.txt . Återigen, det är formaterat för läsbarhet:

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, det händer mycket! Det här är definitivt mer pratsamt än rekorduppsättningen av snapshot-typ. Låt oss gå igenom dem en efter en.

Den första väljer bara CityID kolumn. Det råkar vara den primära nyckeln i tabellen, men ännu viktigare, det är indexet som Access använder på sin sida. Det kommer att bli viktigt när vi studerar synpunkter senare. Access använder den här frågan för att hämta nycklarna och använda den för att fylla i andra frågor senare som vi kommer att se.

Den andra satsen är närmare den ursprungliga ögonblicksbildsfrågan, förutom att vi nu har en ny WHERE klausulfiltrering på CityID kolumn. Av det kan vi se att det är en enradshämtning. Vi kan använda nycklarna vi fick från den första frågan och samla resten av kolumnerna i denna fråga. Närhelst den förberedda satsen körs kommer du att se en SQLExecute: (GOTO BOOKMARK) .

Men det skulle vara ineffektivt om vi var tvungna att göra detta för alla rader... Och det är där nästa fråga kommer in. Den 3:e satsen liknar den 2:a men har 10 predikat. Denna förberedda fråga exekveras med varje SQLExecute: (MULTI_ROW FETCH) . Så vad detta betyder är att när vi laddar ett formulär eller ett datablad eller till och med öppnar en postuppsättning i VBA-kod, kommer Access att använda antingen versionen med en rad eller flera rader och fyller i parametrarna med hjälp av nycklarna som den fick från den första fråga.

Bakgrundshämtning och omsynkronisering

Förresten, har du någonsin lagt märke till hur när du öppnar ett formulär eller ett datablad, du inte får se "X på Y" i navigeringsfältet?

Det beror på att Access inte kan veta hur många det finns förrän den har samlat in resultaten från den första frågan. Det är därför du ofta upptäcker att det går väldigt snabbt att öppna en fråga som returnerar stora mängder data. Du förhandsgranskar bara ett litet fönster av hela postuppsättningen medan Access hämtar raderna i bakgrunden. Om du klickar på knappen "Gå till sist" kanske du upptäcker att den fryser åtkomst. Du måste vänta tills den har hämtat alla nycklar i den första frågan innan vi kan se "X på Y" i navigeringsfältet.

Därför kan du förstå hur Access kan ge illusionen av att vara snabb att öppna även en stor postuppsättning när vi använder en rekorduppsättning av dynasettyp och det är vanligtvis en bra upplevelse för användaren.

Slutligen måste vi notera att vi har 3 olika typer av körningar, SQLExecDirect , SQLPrepare och SQLExecute . Du kan se att med den förra har vi inga parametrar. Frågan är helt enkelt som den är. Men om en fråga behöver parametriseras måste den först förberedas via SQLPrepare och sedan exekveras med SQLExecute med angivna värden för parametrar. Vi kan inte se vilka värden som faktiskt skickades till SQLExecute uttalande även om vi kan sluta oss till det vi ser i Access. Du kan bara veta om den hämtade en enda rad (med SQLExecute: (GOTO BOOKMARK) eller flera rader (med SQLExecute: (MULTI-ROW FETCH) ). Access kommer att använda versionen med flera rader för att göra bakgrundshämtning och fylla postuppsättningen stegvis, men använda versionen med en rad för att fylla endast en rad. Det kan vara fallet för en enskild formulärvy i motsats till kontinuerlig formulär- eller databladsvy eller använd den för omsynkronisering efter en uppdatering.

Navigera runt

Med en tillräckligt stor postuppsättning kanske Access inte någonsin kan slutföra att hämta alla poster. Som nämnts tidigare presenteras användaren med data så snart som möjligt. Normalt, när användaren navigerar framåt genom postuppsättningen, kommer Access att fortsätta att hämta fler och fler poster för att hålla bufferten före användaren.

Men anta att användaren hoppar till 100:e raden genom att gå till navigeringskontrollen och ange 100 där?

I så fall kommer Access att skicka följande frågor...

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (GOTO BOOKMARK)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Notera hur Access använder de redan förberedda satserna som skapades vid tidpunkten för öppning av postuppsättningen. Eftersom den redan har nycklarna från den första frågan, kan den veta vilken som är den "100:e" raden. För att använda ett mer konkret exempel. Anta att vi hade CityID börjar på 1, 3, 4, 5…99, 100, 101, 102 utan post för CityID = 2 . I den första frågan, CityID 101 skulle vara på 100:e raden. Därför, när användaren hoppar till 100, söker Access upp den 100:e raden i den första frågan, se att det är CityID 101, tar sedan det värdet och matar in det i SQLExecute: (GOTO BOOKMARK) för att omedelbart navigera till den posten. Den tittar sedan på de kommande 10 posterna och använder de efterföljande CityID för att fylla bufferten med flera SQLExecute: (MULTI-ROW FETCH) . Du kanske har märkt att det finns en hämtning av flera rader före hämtning av en enda rad. Access hämtar faktiskt de 101:e-110:e raden i hämtning av flera rader och hämtar den 100:e posten i nästa enstaka radhämtning.

När Access har fått data för raderna på 100:e. Det tar användaren dit, och börja sedan fylla upp bufferten runt den 100:e raden. Det gör att användaren kan se den 100:e raden utan att behöva vänta med att ladda alla 11:e-99:e posterna. Användaren har också uppenbarligen snabb surfupplevelse när användaren klickar på föregående eller nästa från den nya positionen eftersom Access redan laddade den i bakgrunden innan användaren bad om det. Det bidrar till att ge illusionen av att vara snabb även över ett långsamt nätverk.

Men även om användaren lämnade formuläret öppet och inaktivt, skulle Access fortsätta att utföra både bakgrundshämtning och uppdatera bufferten för att undvika att visa användarens inaktuella data. Det styrs av ODBC-inställningarna i dialogrutan Alternativ, under avsnittet Avancerat på fliken Klientinställningar:

Standardinställningen för ODBC-uppdateringsintervall är 1500 sekunder men kan ändras. Det kan också ändras via VBA.

Slutsatser:Chunky eller Chatty

Du bör nu se att huvudorsaken till att rekorduppsättningar av dynaset-typ är uppdateringsbara men rekorduppsättningar av snapshot-typ inte är för att Access kan ersätta en rad i postuppsättningen med den senaste versionen av densamma från servern eftersom den vet hur man väljer en en rad. Av den anledningen måste Access hantera 2 ODBC-frågor; en för att hämta nycklarna och en för att hämta det faktiska innehållet i rader för en given nyckel. Den informationen fanns inte med en postuppsättning av snapshottyp. Vi har precis fått en stor klick data.

Vi tittade på 2 huvudtyper av rekorduppsättningar även om det finns fler. Andra är dock bara varianter av de två typerna vi täckte. Men för nu räcker det att komma ihåg att att använda snapshot är att vara chunky i vår nätverkskommunikation. Å andra sidan, att använda dynaset betyder att vi blir pratsamma. Båda har sina upp- och nedgångar.

Till exempel behöver snapshot recordset ingen ytterligare kommunikation med servern när den väl har hämtat data. Så länge postuppsättningen är öppen kan Access fritt navigera runt sin lokala cache. Access behöver inte heller ha några lås och därmed blockera andra användare. En snapshot-postuppsättning är dock av nödvändighet långsammare att öppna eftersom den måste samla in all data i förväg. Det kan passa dåligt för en stor postuppsättning, även om du tänker läsa all data.

Anta att du skapar en stor Access-rapport som är på 100 sidor, är det vanligtvis värt att använda dynaset-typ recordset. Den kan börja rendera förhandsgranskningen så snart den har tillräckligt för att rendera den första sidan. Det är bättre än att tvinga dig att vänta tills den har hämtat all data innan den kan börja rendera förhandsgranskningen. Även om en dynaset-postuppsättning kan ta lås, är det vanligtvis för en kort tid. Det är bara tillräckligt länge för att Access ska synkronisera om sin lokala cache.

Men när vi tänker på hur många fler förfrågningar som Access skickar över nätverket med en rekorduppsättning av dynaset-typ, är det lätt att se att om nätverksfördröjningen är dålig kommer Access prestanda att lida i enlighet därmed. För att Access ska tillåta användare att redigera och uppdatera datakällor på ett generiskt sätt krävs att Access håller reda på nycklar för att välja och ändra en enskild rad. Vi kommer att titta på detta i de kommande artiklarna. I nästa artikel kommer vi att titta på hur sortering och grupper påverkar en postuppsättning av dynaset-typ samt hur Access bestämmer nyckeln som ska användas för en postuppsättning av dynaset-typ.

För mer hjälp med Microsoft Access, ring våra experter på 773-809-5456 eller maila oss på [email protected].


  1. få ett antal unika värden utan att separera värden som hör till samma värdeblock

  2. Hur man lagrar Java Date till Mysql datetime med JPA

  3. Skillnaden mellan SELECT INTO och INSERT INTO i MySQL

  4. konvertera Excel Date Serienummer till Vanligt Datum