AKTUALIZACE: Přidáno několik dalších vysvětlení významu SQLExecute
a jak Access zpracovává připravené dotazy. Díky, Bobe!
Co dělá Access, když procházíme a prohlížíme záznamy v propojené tabulce ODBC?
Ve druhé části naší série trasování ODBC se zaměříme na dopad typů sad záznamů v propojené tabulce ODBC. V minulém článku jsme se dozvěděli, jak zapnout ODBC SQL trace a nyní můžeme vidět výstup. Pokud jste si s tím trochu pohráli, možná jste si všimli, že váš Access dotaz a ODBC SQL příkazy, které Access generuje, nevypadají příliš podobně. Poskytneme také podrobný pohled na to, jak typy ovlivňují chování dotazů SELECT, a také se podíváme na různé varianty sad záznamů, jako jsou snímky a dynamické sady.
Pokud chcete pokračovat, můžete použít ukázkovou databázi, kterou najdete zde.
Účinek typů sady záznamů ve SELECT dotazu
Typy sady záznamů mají velký vliv na to, jak bude Access komunikovat se zdroji dat ODBC. Možná jste si všimli, že v zobrazení návrhu formuláře nebo v zobrazení návrhu dotazu můžete nastavit typ sady záznamů. Ve výchozím nastavení je nastavena na Dynaset
.
Ve VBA máme několik dalších možností, ale o to se zatím nebudeme starat. Začněme pochopením toho, co přesně Dynaset
a Snapshot
znamená první. Začneme méně často používaným typem Snapshot
první.
Sada záznamů typu snímek
Snapshot
je docela jednoduchý. V podstatě to znamená, že pořídíme snímek výsledku v době provádění dotazu. Normálně to také znamená, že Access nemůže aktualizovat výsledek. Podívejme se však na to, jak Access dotazuje zdroj pomocí sady záznamů založené na snímku. Můžeme vytvořit nový Access dotaz takto:
SQL, jak můžeme vidět v zobrazení SQL dotazu Accessu, je:
SELECT Cities.* FROM Cities;Spustíme dotaz a pak se podíváme na
sqlout.txt
soubor. Zde je výstup naformátovaný pro čitelnost: SQLExecDirect: SELECT "CityID" ,"CityName" ,"StateProvinceID" ,"Location" ,"LatestRecordedPopulation" ,"LastEditedBy" ,"ValidFrom" ,"ValidTo" FROM "Application"."Cities"Mezi tím, co jsme napsali v dotazu Accessu, bylo jen málo rozdílů v porovnání s tím, co Access odeslal do ODBC, které budeme analyzovat.
- Přístup kvalifikoval tabulku s názvem schématu. Je zřejmé, že v dialektu Access SQL to nefunguje stejným způsobem, ale pro dialekt ODBC SQL je užitečné zajistit, že vybíráme ze správné tabulky. To se řídí
SourceTableName
vlastnictví. - Přístup rozšířil obsah
Cities.*
do výčtového seznamu všech sloupců, o kterých Access již ví na základěFields
kolekce podkladovéhoTableDef
objekt. - Přístup používá
"
citovat identifikátory, což je to, co ODBC SQL dialekt očekává. Přestože Access SQL i Transact-SQL používají k citování identifikátoru závorky, není to legální syntaxe v dialektu ODBC SQL.
Takže i když jsme provedli pouze jednoduchý dotaz na snímek a vybrali jsme všechny sloupce pro tabulku, můžete vidět, že Access provádí mnoho transformací do SQL mezi tím, co vložíte do zobrazení návrhu dotazu Access nebo zobrazení SQL, a tím, co Access skutečně vysílá do dat. zdroj. V tomto případě je však většinou syntaktický, takže v příkazu SQL není žádný skutečný rozdíl mezi původním dotazem Accessu a příkazem SQL ODBC.
Trasování také přidalo SQLExecDirect
na začátku SQL příkazu. Jakmile se podíváme na několik dalších příkladů, vrátíme se k tomu.
Sady záznamů typu Dynaset
Použijeme stejný dotaz, ale vlastnost změníme zpět na výchozí Dynaset
.
Spusťte to znovu a uvidíme, co získáme z sqlout.txt
. Opět je naformátován pro čitelnost:
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)Páni, děje se spousta věcí! To je rozhodně upovídanější než sada záznamů typu snapshot. Pojďme si je projít jeden po druhém.
První vybere pouze CityID
sloupec. To je náhodou primární klíč tabulky, ale co je důležitější, je to index, který Access používá na své straně. To bude důležité, až si názory prostudujeme později. Access používá tento dotaz k získání klíčů a později je použije k vyplnění dalších dotazů, jak uvidíme.
Druhý příkaz je bližší původnímu dotazu na snímek, kromě toho, že nyní máme nový WHERE
filtrování klauzulí na CityID
sloupec. Z toho můžeme vidět, že se jedná o jednořadé načítání. Můžeme použít klíče, které jsme získali z prvního dotazu, a shromáždit zbývající sloupce v tomto dotazu. Kdykoli se provede tento připravený příkaz, zobrazí se SQLExecute: (GOTO BOOKMARK)
.
Ale to by bylo neefektivní, kdybychom to museli dělat pro všechny řádky... A tam přichází na řadu další dotaz. 3. příkaz je podobný druhému, ale má 10 predikátů. Tento připravený dotaz se provede s každým SQLExecute: (MULTI_ROW FETCH)
. To znamená, že když načteme formulář nebo datový list nebo dokonce otevřeme sadu záznamů v kódu VBA, Access použije buď jednořádkovou verzi, nebo víceřádkovou verzi a vyplní parametry pomocí klíčů, které získal z prvního dotaz.
Načítání na pozadí a opětovná synchronizace
Mimochodem, všimli jste si někdy, že když otevřete formulář nebo datový list, nevidíte na navigačním panelu „X z Y“?
Je to proto, že Access nemůže vědět, kolik jich je, dokud nedokončí sběr výsledků z prvního dotazu. Proto můžete často zjistit, že je velmi rychlé otevřít dotaz, který vrací velké množství dat. Prohlížíte pouze malé okno celé sady záznamů, zatímco Access načítá řádky na pozadí. Pokud kliknete na tlačítko „Přejít na poslední“, možná zjistíte, že přístup zamrzne. Než v navigační liště uvidíme „X z Y“, museli byste počkat, dokud nedokončí načítání všech klíčů v prvním dotazu.
Můžete tedy ocenit, jak může Access poskytnout iluzi rychlého otevření i velké sady záznamů, když používáme sada záznamů typu dynaset a to je pro uživatele obvykle dobrá zkušenost.
Nakonec musíme poznamenat, že máme 3 různé typy spouštění, SQLExecDirect
, SQLPrepare
a SQLExecute
. Můžete vidět, že u prvního nemáme žádné parametry. Dotaz je prostě takový, jaký je. Pokud je však třeba dotaz parametrizovat, musí být nejprve připraven pomocí SQLPrepare
a poté později spuštěn pomocí SQLExecute
s hodnotami pro poskytnuté parametry. Nevidíme, jaké hodnoty byly ve skutečnosti předány do SQLExecute
i když to můžeme odvodit z toho, co vidíme v Accessu. Můžete pouze vědět, zda načetla jeden řádek (pomocí SQLExecute: (GOTO BOOKMARK)
nebo více řádků (pomocí SQLExecute: (MULTI-ROW FETCH)
). Access použije verzi s více řádky k načítání na pozadí a přírůstkovému vyplnění sady záznamů, ale k vyplnění pouze jednoho řádku použije verzi s jedním řádkem. To může být případ zobrazení jednoho formuláře na rozdíl od zobrazení souvislého formuláře nebo datového listu nebo jej použít k opětovné synchronizaci po aktualizaci.
Navigace v okolí
S dostatečně velkou sadou záznamů nemusí být Access schopen někdy dokončit načítání všech záznamů. Jak již bylo uvedeno dříve, uživateli jsou data předložena co nejdříve. Za normálních okolností, když uživatel projde sadou záznamů dopředu, Access bude neustále načítat další a další záznamy, aby udržela vyrovnávací paměť před uživatelem.
Ale předpokládejme, že uživatel přejde na 100. řádek tím, že přejde na ovládací prvek navigace a zadá tam 100?
V takovém případě Access odešle následující dotazy…
SQLExecute: (MULTI-ROW FETCH) SQLExecute: (GOTO BOOKMARK) SQLExecute: (MULTI-ROW FETCH) SQLExecute: (MULTI-ROW FETCH)Všimněte si, jak Access používá již připravené příkazy, které vytvořil v době otevření sady záznamů. Protože již má klíče z prvního dotazu, je schopen vědět, který je „100.“ řádek. Abych použil konkrétnější příklad. Předpokládejme, že máme
CityID
začínající na 1, 3, 4, 5…99, 100, 101, 102 bez záznamu pro CityID = 2
. V prvním dotazu CityID
101 by bylo ve 100. řadě. Proto, když uživatel přejde na 100, Access vyhledá 100. řádek v prvním dotazu, uvidí, že je to CityID
101, pak vezme tuto hodnotu a vloží ji do SQLExecute: (GOTO BOOKMARK)
k okamžitému přechodu na daný záznam. Poté se podívá na dalších 10 záznamů a použije tyto následující CityID
k naplnění vyrovnávací paměti několika SQLExecute: (MULTI-ROW FETCH)
. Možná jste si všimli, že před načtením jednoho řádku je načteno několik řádků. Access ve skutečnosti načítá 101. až 110. řádky v načítání více řádků a načítá 100. záznam v dalším načítání jednoho řádku. Jakmile Access získá data pro řádky na 100. řádku, zavede uživatele tam a poté začne plnit vyrovnávací paměť kolem tohoto 100. řádku. To umožňuje uživateli zobrazit 100. řádek, aniž by musel čekat na načtení všech 11. až 99. záznamů. Uživatel má také zjevně rychlé procházení, když uživatel klikne na předchozí nebo další z nové pozice, protože Access ji již načetl na pozadí, než o to uživatel požádal. To pomáhá vytvářet iluzi rychlosti i přes pomalou síť.
Ale i kdyby uživatel nechal formulář otevřený a nečinný, Access by nadále prováděl načítání na pozadí a obnovoval vyrovnávací paměť, aby se zabránilo zobrazení zastaralých dat uživatele. To se řídí nastavením ODBC v dialogovém okně Možnosti v části Upřesnit na kartě Nastavení klienta:
Výchozí hodnota pro interval obnovení ODBC je 1500 sekund, ale lze jej změnit. Lze jej také změnit pomocí VBA.
Závěry:robustní nebo upovídaný
Nyní byste měli vidět, že hlavním důvodem, proč jsou sady záznamů typu dynaset aktualizovatelné, ale sady záznamů typu snapshot nikoli, je ten, že Access dokáže nahradit řádek v sadě záznamů nejnovější verzí téhož ze serveru, protože ví, jak vybrat jeden řádek. Z tohoto důvodu potřebuje Access spravovat 2 dotazy ODBC; jeden pro načtení klíčů a druhý pro načtení skutečného obsahu řádků pro daný klíč. Tyto informace nebyly k dispozici u sady záznamů typu snímek. Právě jsme získali velký blok dat.
Podívali jsme se na 2 hlavní typy sad záznamů, i když jich je více. Ostatní jsou však jen varianty 2 typů, které jsme probrali. Pro tuto chvíli však postačí zapamatovat si, že použití snapshotu znamená být v naší síťové komunikaci robustní. Na druhou stranu, použít dynaset znamená, že budeme mluvit. Oba mají své mouchy.
Například sada záznamů snímku nepotřebuje žádnou další komunikaci se serverem, jakmile načte data. Dokud sada záznamů zůstane otevřená, Access může volně procházet místní mezipamětí. Přístup také nemusí držet žádné zámky a blokovat tak ostatní uživatele. Snímek záznamů se však nutně otevírá pomaleji, protože musí předem shromáždit všechna data. Může se nehodit pro velkou sadu záznamů, i když máte v úmyslu číst všechna data.
Předpokládejme, že vytváříte velkou sestavu Accessu, která má 100 stránek, obvykle se vyplatí použít sadu záznamů typu dynaset. Může začít vykreslovat náhled, jakmile bude mít dostatek k vykreslení první stránky. To je lepší, než vás nutit čekat, dokud nenačte všechna data, než začne vykreslovat náhled. Ačkoli sada záznamů dynaset může trvat zámky, obvykle je to na krátkou dobu. Je pouze dostatečně dlouhá, aby Access znovu synchronizoval svou místní mezipaměť.
Když se však zamyslíme nad tím, kolik dalších požadavků Access odešle přes síť se sadou záznamů typu dynaset, je snadné vidět, že pokud je latence sítě nízká, výkon Accessu tím utrpí. Aby Access umožnil uživatelům upravovat a aktualizovat zdroje dat obecným způsobem, vyžaduje, aby Access sledoval klíče pro výběr a úpravu jednoho řádku. Na to se podíváme v nadcházejících článcích. V příštím článku se podíváme na to, jak řazení a skupiny ovlivňují sadu záznamů typu dynaset a také na to, jak Access určuje klíč, který se má použít pro sadu záznamů typu dynaset.
Pro další pomoc s Microsoft Access zavolejte našim odborníkům na číslo 773-809-5456 nebo nám napište na [email protected].