Vzdálená data - skoro každý už o tom slyšel, ale ti začínající si kladou otázky:
- Jak na to ?
- Jaké tam jsou podrazy ?
- Vyplatí se to ?
Na vzdálená data se dá přistupovat pomocí nativní vrstvy pro podporu ODBC ve VFP nebo pomocí objektů DAO a OLE-DB. V samotné VFP lze na RD přistupovat programově pomocí SPT (SQL Pass Through) či spojení a pohledy definovat visuálně v DBC konteineru.
Nebudu se zde zabývat jak visuálně definovat spojení a pohledy na RD, či otevírat spojení a tahat data pomocí SPT. Hodlám poukázat na rozdíly mezi visuálním návrhem a SPT a na různé špeky.
Obecné výhody visuálního návrhu:
Obecné nevýhody visuálního návrhu:
Obecné výhody SPT:
Obecné nevýhody SPT:
1a) Obecný popis:
Definice spojení mezi visuálním návrhem a SPT se nijak neliší. V obou případech se lze odkazovat na DSN či přímo definovat ConnectString. V samotném ConnectString-u lze definovat DSN nebo přímo ODBC driver.
Spojení uložené v DBC konteineru lze otevřít pomocí funkce SQLCONNECT(), kde se jako parametr použije název spojení v DBC konteineru.
Spojení přes SPT se otevírá pomocí funkcí
* Otevření spojení z DBC konteineru LOCAL lihdbc lihdbc=SQLCONNECT("MOJE_SPOJENI_V_DBC_KONTEINERU") * Otevření spojení přes SPT lihdbc=SQLCONNECT("MOJE_DSN","Uziv1","heslo1") * Otevření spojení přes SPT pomocí definovaného ConnectStringu přes DSN lihdbc=SQLSTRINGCONNECT("DSN=MOJE_DSN;uid=Uziv1;pwd=Heslo1;") * Otevření spojení přes SPT pomocí definovaného ConnectStringu přes určení ODBC driveru lihdbc=SQLSTRINGCONNECT("driver={Microsoft Access driver (*.mdb)};dbq=rdatab.mdb;uid=Uziv1;pwd=Heslo1")
Název | Deaultní hodnota | Popis | Nutné nastavit na 0. spojení |
Poznámka |
IdleTimeOut | 0 | Čas v minutách+1, po kterém VFP automaticky ukončí ODBC spojení. Po použití ODBC handlu VFP automaticky ODBC spojení obnoví. |
Ano | Pokud je 0, spojení se nikdy neukončí. Toto však bohužel přestává korektně fungovat po nainstalování MDAC 2.0 a vyšší. Tato činnost je však nyní přímo implemetována jako součást Poolingu v ODBC manageru. |
PacketSize | 4096 | Velikost paketu v bytes v síťovém provozu | Ano | Většinou je toto nastavení ingorováno, neb si jej nastaví sám databázový server. |
DispLogin | 1 | Způsob zobrazení přihlašovacího dialogu. | Ano | Tato volba umožňuje říci, zda se má spustit přihlašovací dialog ODBC driveru , pokud nějaké důležité údaje chybí. |
ConnectTimeOut | 15 | Čas v sekundách, po kterém se vyhlásí time-out error. | Ano | Pokud se tato vlastnost nastaví (>0), aplikace nezatuhne. |
QueryTimeOut | 0 | Čas v sekundách, po kterém se vyhlásí generální time-out error. | Ano | Pokud se tato vlastnost nastaví (>0), aplikace nezatuhne. |
WaitTime | 600 | Čas v ms po ketrém VFP kontroluje, zda již byl příkaz vykonán. | Ano | Čím větší čas, tím menší komunikace mezi klientem a serverem a tím pádem i méně přetížená síť. |
Asynchronous | .F. | Příznak zda je spojení v režimu asynchronním. | Ne | Pokud je .T., pak VFP umožňuje na takto více nastavených spojení naráz spuštět SQL příkazy a otevírat pohledy. |
DispWarnings | .F. | Příznak, zda se mají zobrazovat varovná hlášení ODBC driveru při nastavování vlastností. | Ne | Pokud je nastaveno .T., pak u starších ODBC driverů nedošlo ke spojení Abych pravdu řek, většinou tyto hlašení v ostrém provozu lidi rozčilujou. |
BatchMode | .T. | Příznak, zda funkce SQLEXEC() vrátí výsledky vícenásobného SQL příkazu najednou či postupně pomocí funkce SQLMORERESULT(). | Ne | Doporučuji ponechat defaultní nastavení .F., ušetříte si tím spoustu starostí. |
Transactions | 1 | Příznak , zda jsou transakce automatické či ruční. | Ne | Na většinu případů stačí automatické transakce (ukládání jedné věty v pohledu). Pokud je však nutno provést změny ve více tabulkách a nejde to pomocí uložených procedur (třeba v takovým MS Accessu je to vo hubu) pak se nastaví ruční transakce. Pro potvrzení změn se použije funkce SQLCOMMIT() a pro zrušení změn SQLROLLBACK(). |
1c) Batch processing (provedení více SQL příkazů pomocí funkce SQLEXEC()):
1ca) Vlastnost BatchMode = .T.
Pokud proběhly všechny SQL příkazy v pořádku, funkce SQLEXEC() 1. Pokud jsou v SQL příkazu pouze SELECTy pak, vrátí počet provedených SELECTů (nebo vytvořených VFP kurzorů).
* Vyvolání dvou SELECTů najednou SQLEXEC(1,"SELECT * FROM XXT001;SELECT * FROM XXT002","test") * Vyvolání dvou UPDATEů najednou SQLEXEC(1,"UPDATE XXT001 SET XX002 = 0 WHERE XX001='A';UPDATE XXT002 SET XX002 = 0 WHERE XX001='B'")Pokud je spouštěno několik SELECTů, pak VFP vytvoří kurzory jejichž název vychází z uvedeného 3. parametru (pokud nebyl zadán, pak první kurzor má název SQLResult a další SQLResult1,SQLResult2 ...).
1d) Asynchronní/Synchronní provoz:
Pokud nedošlo ke zmeně vlastnosti Asynchronous na 0. spojení (DE,Runtime), nebo ke změně nastavení VFP (DE), pak je spojení otevíráno v režimu synchronním. Velice dobrý popis rozdílů mezi asynchronním a synchronním režimem je v samotném helpu VFP.
Synchronní režim se používá pokud je potřeba co nejrychleji vykonat SQL příkaz a nevadí, že po tu dobu bude aplikace zablokovaná.
Funkce SQLEXECUTE() či SQLMORERESULT() vrací 1 pokud nic neselhalo, -1 pokud selhal SQL příkaz či -2 pokud došlo k chybě na úrovni spojení.
Asynchronní režim se používá pokud je potřeba postupně načítat data na pozadí či na požádání nebo spouštět naráz více SQL příkazů na různých spojení (všechna musí být v asynchronním režimu).
Funkce SQLEXECUTE() vrací 0 dokud není SQL příkaz komletně vykonán, 1 pokud je SQL příkaz kompletně vykonán a nic neselhalo, -1 pokud selhal SQL příkaz či -2 pokud došlo k chybě na úrovni spojení (chování fukce SQLMORERESULT() je popsáno v části 1c) Batch processing).
1e) Transakce:
Standardně jsou na spojení nastaveny automatické transakce, to znamená, že po vykonaní každého příkazu INSERT,UPDATE či DELETE jsou změny nevratné.Pokud by bylo potřeba jednu větu větu založit, další opravit a smazat nějaký blok dat a při selhání jednoho z oněch příkazů vrátit zpět původní stav, pak se musí nastavit na spojení ruční transakce.
* Spojení je už otevřeno, v synchronním režimu =SQLSETPROP(lihdbc,"Transactions",2) && Nastav ruční transakce * Proveď INSERT,UPDATE,DELETE liErr=SQLEXEC(lihdbc,"INSERT INTO XXT001 (XX001,XX002) VALUES ('AAAA','BBBBB')") IF liErr=1 liErr=SQLEXEC(lihdbc,"UPDATE XXT001 SET XX002='BBBBB' WHERE XX001='AAAA'") ENDIF IF liErr=1 liErr=SQLEXEC(lihdbc,"DELETE FROM XXT001 WHERE XX001='AAAA'") ENDIF * Pokud došlo k chybě musí se vrátit změny IF liErr<0 =SQLROLLBACK(lihdbc) ELSE * Jinak se musejí potvrdit liErr=SQLCOMMIT(lihdbc) && i tato funkce může vrátit -1 nebo -2 IF liErr#1 * Zatím se mi nestalo, že by to takhle dopadlo, takže je to tady jen pro jistotu =SQLROLLBACK(lihdbc) ENDIF ENDIF * Nastavení automatických transakcí =SQLSETPROP(lihdbc,"Transactions",1)
Slovníček pojmů a zkratek:
ConnectString - - Spojovací řetězec , jehož některé elementy můžou být specifické pro určitý ODBC driver, ale většina odpovídá standardu ODBC
ODBC driver - - Specifický driver pro konkrétní datový zdroj
DSN - Data Source Name - Název datového zdroje definovaného v ODBC manažeru
DAO - Data Access Object - Objektové rozhraní pro přístup k RD
SPT - -viz SQL Pass Through
SQL Pass Through - - Technologie pro vykonaní nativních příkazů pro datový server
ODBC - Open database connectivity - Univerzální rozhraní pro přístup k různým datovým zdrojům
RD - - Vzdálená data
DE - Developmen Environment - Vývojové prostředí
Runtime - -
OLE-DB - -
ADO - -