27 rozdzial 26 IK5YEFB7LBVB567D Nieznany (2)

background image

Rozdział 26

Borland Database Engine (BDE)

Borland Database Engine (BDE) (mechanizm dostępu do baz danych) jest
zestawem bibliotek DLL, przy pomocy których Delphi realizuje dostęp do baz
danych. Interfejs BDE jest używany nie tylko przez Delphi. Posługują się nim
również inne programy firmy Borland (takie jak Paradox for Windows, Visual
dBASE, Borland C++ Builder itd). W niektórych pakietach programowych tej
firmy, BDE występuje pod starą nazwą IDAPI (Independent Database Application
Programming Interface). Początkowo IDAPI miał być interfejsem otwartych baz
danych, ale na tym polu przegrał z ODBC firmy Microsoft.

Delphi, poprzez swoje komponenty przeznaczone do obsługi baz danych, zawiera
prawie wszystkie właściwości funkcjonalne BDE, toteż niezwykle rzadko zachodzi
konieczność bezpośredniej współpracy z BDE. Metody oferowane przez Delphi są
bez porównania łatwiejsze i bardziej odporne na błędy, niż bezpośrednie
wywołania BDE. Zastosowanie tych komponentów nie redukuje (wbrew pozorom)
efektywności aplikacji.

Stosując bezpośrednie odwołania BDE należy pamiętać o kilku sprawach. Po
pierwsze - nie jest dostępny mechanizm obsługi wyjątków, który biblioteka Delphi
- VCL - zapewnia podczas dostępu do bazy danych. Należy dokładnie sprawdzać
kody zwracane przez funkcje BDE i odpowiednio na nie reagować. Po drugie -
z uwagi na fakt, iż komponenty bazy danych Delphi nie będą świadome niskiego
poziomu dostępu, musimy się liczyć z koniecznością ponownej synchronizacji
z bazą danych. W pewnych sytuacjach może to wymagać tylko wywołania metody
Refresh (odświeżania), w innych - zamknięcia i ponownego otwarcia objektu
DataSet.

W tym rozdziale przyjrzymy się wykorzystaniu BDE, w celu rozszerzenia dostępu
do baz danych w stosunku do zakresu oferowanego przez bibliotekę Delphi - VCL.
Nie traktujemy tutaj BDE jako alternatywy dla VCL, a jedynie jako jej
rozszerzenie. Omówimy podstawową strukturę BDE i funkcje BDE (w zakresie
wymaganym przez twórców aplikacji) oraz metody jednoczesnego stosowania
komponentów Delphi i odwołań BDE API.

BDE kontra ODBC

W zasadzie sterowniki BDE, na tle swych odpowiedników ODBC, wypadają
korzystniej - są szybsze i

charakteryzują się lepszymi właściwościami

background image

746

Część IV

użytkowymi. Do wielu sterowników nie można ponadto uzyskać dostępu bez
wykonywania bezpośrednich odwołań ODBC API - nie są one obsługiwane przez
większość narzędzi poza tymi, które pretendują do zgodności z ODBC.

Inaczej jest w przypadku BDE. Z zasady, oparte o BDE sterowniki SQL Link
obsługują platformy bazy danych w sposób kompleksowy. Ich funkcjonalność
potwierdza się w pracy komponentów baz danych Delphi. Np. serwery baz danych
SQL dysponują mechanizmem kontroli transakcji, który umożliwia grupowanie
porcji zmian w bazie danych z zachowaniem (lub bez) ich kompletności. Składnia
SQL wymaga zapoczątkowania zmian grupy transakcji z serwera do serwera.

Z drugiej strony tabele lokalne nie pozwalają na stosowanie przetwarzania
transakcyjnego. Mimo sprzeczności między producentami w zakresie składni SQL
i mimo braku obsługi transakcji w tabelach lokalnych, BDE zapewnia pojedyncze
odwołanie API do rozpoczęcia transakcji na dowolnej platformie:

DbiBeginTran

. Ta właściwość znajduje nawet zastosowanie dla tabel

lokalnych; BDE tworzy dla nich swój własny mechanizm kontroli transakcji.
Delphi zawiera to odwołanie BDE API w metodzie

BeginTransaction

swojego komponentu

TDatabase

, co pozwala na zainicjowanie transakcji na

platformie serwera, bez odwoływania się do tabeli aktualnej. Tym samym można
stosować przetwarzanie transakcyjne tabel lokalnych, bez względu na
ograniczenia. BDE zapewnia jednolity interfejs API, bez względu na rodzaj
stosowanego systemu zarządzania bazą danych (DBMS).

Architektura

Architektura BDE bazuje na sterownikach - dla każdego stosowanego systemu
obsługi baz danych (DBMS) wymagany jest oddzielny sterownik. Czasami
pojedynczy sterownik obsługuje wiele wersji platform DBMS (np. istnieje jeden
sterownik dla platformy dBASE, bez względu na to, czy mamy do czynienia
z dBASE III, IV lub V, FoxPro lub systemem Clipper).

Rozważając to zagadnienie, lepiej zrozumiemy architekturę BDE. Dostęp z Delphi
do obiektu bazy danych realizowany jest następująco:

1. Odwołanie się do komponentu bazy danych Delphi.

2. Komponent wywołuje BDE.

3. BDE wywołuje swoją lokalną bazę danych lub sterownik SQL Links.

4. Jeśli używany jest sterownik lokalny, wówczas udostępnia on tabele bazy

danych

5. Jeśli używany jest sterownik SQL Links, wywołuje on sterownik klienta

producenta DBMS.

background image

Rozdzial 26 Borland Database Engine (BDE)

747

BDE jest zorientowany obiektowo - charakteryzuje się wygodną obsługą
i łatwością rozszerzania. Jeśli zachodzi potrzeba uzyskania dostępu do platformy
DBMS, dla której BDE nie zapewnia pełnej obsługi, należy po prostu zainstalować
- dedykowany dla tej platformy - sterownik BDE lub ODBC. Jest mało
prawdopodobne, aby trzeba było przerabiać BDE, by mógł obsługiwać nowe
platformy.

BDE jest przygotowany do pracy w trybie klient/serwer - obsługuje wszystkie
zaawansowane funkcje, których użytkownicy oczekują od DBMS typu
klient/serwer. Mamy tutaj na myśli m.in.: przetwarzanie transakcji, aktualizowanie
kursorów, obsługę procedur pamiętanych i inne. Zamiast stosować metodę
najmniejszego wspólnego mianownika do obsługi baz danych, BDE dysponuje
interfejsem API, który jest „superzestawem” funkcji dostępnych na wszystkich,
obsługiwanych przez niego platformach. Ponieważ sterowniki i API nie są z sobą
w powiązane w BDE, przejście z platformy na platformę nigdy nie było łatwiejsze.
Skalowanie związane z

przejściem z

tabel lokalnych na platformy typu

klient/server jest tak łatwe, jak zmiana aliasu bazy danych, stosowanego przez
aplikację do wskazania nowej platformy.

Usługi współdzielone

Mocna strona BDE wynika z faktu, iż oferuje on usługi, które mogą być
współdzielone przez sterowniki baz danych. Często dzięki temu nie trzeba
ustanawiać oddzielnych usług dla każdego sterownika. Ma to pozytywny wpływ na
ogólną efektywność aplikacji i zapewnia zgodność pomiędzy driverami.

Usługi systemu operacyjnego (OS)

Ponieważ BDE udostępnia swoim sterownikom pełny zestaw usług, izolując je od
bezpośredniego kontaktu z systemem operacyjnym i siecią, jest on w dużej mierze
od niego niezależny.

Menadżer bufora

Pierwszą usługą systemu operacyjnego jest Współdzielony menadżer bufora,
oparty na priorytetach i umożliwiający współdzielenie tego samego dynamicznego
obszaru bufora przez wszystkie sterowniki BDE. Aczkolwiek stosowanie obszaru
dynamicznego nie jest konieczne, sterowniki wykorzystujące wspólny obszar
dynamiczny oszczędzają zasoby systemu.

background image

748

Część IV

Menadżer pamięci

Aby zwiększyć wydajność przydziału mniejszych obszarów pamięci, BDE
dysponuje swoim własnym mechanizmem przydziału pomocniczego. Dzięki niemu
sterowniki nie muszą każdorazowo odwoływać się do systemu operacyjnego, gdy
potrzebują małej ilości pamięci. BDE przydziela większe fragmenty pamięci RAM
i następnie przekazuje je klientowi zgłaszającemu żądania jej przydziału.

Bufor danych typu BLOB

W celu przyspieszenia dostępu do obiektów typu BLOB, BDE zapewnia bufor
danych BLOB. Pamięć ta uwalnia programistów od konieczności zakładania
własnych buforów. Umożliwia ponadto swobodny dostęp do informacji typu
BLOB - tak, by użytkownicy BDE nie musieli się zajmować zapisywaniem
zawartości tego typu danych do pliku zewnętrznego. Ten swobodny dostęp
realizowany jest nawet na platformach, które - ze swojej strony - nie zapewniają
dostępu do danych tego typu.

Mechanizm sortowania

BDE zapewnia szybki mechanizm sortowania, wykorzystywany przez mechanizm
zapytań, sterowniki dBASE i Paradoxa. Firma Borland posiada dwa różne patenty
na architekturę tych mechanizmów sortowania.

Mechanizm zapytań

Aparat zapytań BDE jest mocnym, pełnowartościowym procesorem zapytań, który
szybko wytwarza pełne zestawy wynikowe. Mechanizm ten obsługuje zarówno
metody Zapytanie przez przykład (QBE- Query By Example) i bezpośrednio
metody SQLa - zapytywania baz danych za pośrednictwem każdego,
obsługiwanego przezeń sterowników. SQL można np. wykorzystywać do zapytania
tabel dBASE, nawet w przypadku tabel lokalnych, pozbawionych właściwej
obsługi przetwarzania zapytań SQL.

Generator SQL

Jak już wspomniano, BDE umożliwia tworzenie zapytań baz danych przy pomocy,
znanej z Paradoxa, metody QBE lub używając tradycyjnych instrukcji SQL. Gdy
zapytanie QBE przesyłane jest do serwera SQL, tłumaczone jest najpierw przez
BDE na SQL.

background image

Rozdzial 26 Borland Database Engine (BDE)

749

Restrukturyzacja

Usługa współdzielona Restrukturyzacja umożliwia wykonanie modyfikacji
struktur tabel dBASE i Paradox, bez konieczności zaznajamiania się z szczegółami
tego procesu. Obsługuje ona automatyczne tworzenie tymczasowych tabel lub
zapisywanie i ponowne ładowanie danych.

Usługa translacji danych

BDE dostarcza usługę realizującą translację danych pomiędzy różnymi formatami.
Właściwość ta pozwala funkcjom i usługom na operacje między bazami danych.
W przypadku konwersji pomiędzy podobnymi formatami, usługa określa najlepszą
metodę konwersji i wykonuje ją.

Funkcje integralnej obsługi tabel

BDE zapewnia potężny mechanizm służący do przenoszenia danych z jednego
formatu na inny oraz do obsługi łączenia podobnych do siebie tabel. Usługa ta jest
podstawą komponentu Delphi -

TBatchMove

i programu narzędziowego Data

Pump.

Tabele w pamięci

Podobnie w przypadku, gdy mamy do czynienia z wieloma platformami DBMS
klient/serwer, BDE obsługuje tabele tymczasowe, które istnieją tylko w pamięci.
Usługa ta przyspiesza dostęp do danych, zwiększa efektywność sortowania
i zapewnia niezbędne podstawy dla uaktualnień buforowanych.

Kursory łączone

BDE obsługuje kursory łączone na poziomie mechanizmu, zaspakajając potrzebę
VCL Delphi, uwalnia jednocześnie projektanta aplikacji od zajmowania się tym
problemem. Łączenie jednego kursora z

innym powoduje przejście

przemieszczanie się jednego kursora w czasie zmian drugiego. Zwykle kursor
łączony stosowany jest podczas ustanawiania związków ogólny/szczegółowy
między tabelami.

Usługi sterowników SQL

Dla sterowników bazujących na SQL dostarczana jest seria mini usług - m.in.
translacja komend nawigacyjnych do SQL-a (dzięki czemu dysponować możemy

background image

750

Część IV

łatwiejszym dostępem do tabel lokalnych i SQL), słownik danych i usługi
katalogowe obiektów oraz manipulacja buforowanymi polami typu BLOB.

Menadżer systemu

W razie konieczności Menadżer systemu dla BDE ładuje sterowniki i zwalnia
zasoby, gdy nie są one już dłużej potrzebne.

Menadżer konfiguracji

Usługa zarządzania konfiguracją BDE umożliwia klientom odczyt i

zapis

informacji dotyczącej konfiguracji sterownika. Menadżer umożliwia tworzenie
aliasów, zapytań o parametry sterowników itd.

Sterowniki językowe

Dzięki sterownikom językowym BDE, twórcy aplikacji nie muszą się martwić
o zachowanie BDE w przypadku zmiany języka.

BDE API

BDE API jest interfejsem użytkownika API, zapewniającym pojedynczy
i zunifikowany zestaw odwołań API, zarówno dla zasobów baz danych opartych
o ISAM, jak i zdalnych. Każdy typ bazy danych ma dedykowany sobie interfejs
API. Stąd nawet, gdyby dwukierunkowa nawigacja pomiędzy obiektami bazy
danych serwera SQL nie była właściwie obsługiwana przez producentów DBMS,
Delphi zapewnia ją (w obu kierunkach) w zdalnych zbiorach wynikowych (czego
moglibyśmy oczekiwać normalnie od tabel lokalnych, ale nie od zdalnych). Co
więcej - mimo, iż dBASE i Paradox, jako formaty plików lokalnych, nie posiadają
wbudowanej obsługi transakcji, BDE zapewnia dla nich mechanizm kontroli
transakcji, który wykorzystuje te same odwołania API jak platformy, które te
transakcje obsługują.

BDE API (co można odczytać jedynie pozytywnie) nie obsługuje wszelkich
elementów właściwych każdej platformie DBMS, dla której pracuje. Stąd np.
indeksy systemu Clipper są teraz obsługiwane przez sterownik BDE dBASE,
indeksy pierwotne natomiast - przez sterownik systemu Paradox. Procedury
pamiętane obsługiwane są na tych platformach SQL, które mają je wbudowane itd.

background image

Rozdzial 26 Borland Database Engine (BDE)

751

Minimalne właściwości funkcjonalne

Na platformach, dla których dostępny jest rodzimy sterownik BDE lub ODBC,
dostępne będą zawsze następujące funkcje:

„Otwieranie/zamykanie baz danych

„Pobieranie/nadawanie wartości właściwości w obiektach baz danych

„Odczytywanie/zapisywanie danych w obiektach baz danych

„Tworzenie obiektów baz danych, takich jak tabele i indeksy

„Wykonywanie operacji między bazami danych - jak kopiowanie jednej bazy do

innej

Podstawowe struktury BDE

Aby stworzyć aplikację współpracującą z BDE, powinniśmy znać podstawowe,
wykorzystywane przez ten mechanizm, struktury danych (tabela 26.1):

Tabela 26.1 Podstawowe struktury danych BDE

Struktura

Opis

BATTb1Desc

Integralny deskryptor tabeli

CANHdr

Nagłówek klasy węzła filtra

CBPROGRESSDesc

Procedura zwrotna wskaźnika postępu

RESTcbDESC

Procedura zwrotna restrukturyzacji tabeli

CFGDesc

Deskryptor konfiguracji

CLIENTInfo

Informacja o aplikacji klienta

CRTb1Desc

Deskryptor atrybutów tabeli

DBDesc

Deskryptor bazy danych

DBIEnumFld

Pole wyliczeniowe

DBIEnv

Deskryptor środowiska BDE

DBIErrInfo

Deskryptor informacji o błędzie

DBIQryProgress

Wskaźnik statusu zapytania

DRVType

Deskryptor informacji o sterowniku

FILEDesc

Deskryptor pliku

background image

752

Część IV

Struktura

Opis

FILTERInfo

Deskryptor informacji o filtrze

FLDDesc

Deskryptor pola

FLDType

Deskryptor typu pola

FMLDesc

Deskryptor sterownika języka

FMTBcd

Format liczby dziesiętnej kodowanej dwójkowo

FMTDate

Format danej

FMTNumber

Format liczby

FMTTime

Format czasu

DbiFUNCArgDesc

Deskryptor argumentu funkcji zdalnego zasobu
danych

DbiFUNCDesc

Deskryptor funkcji zdalnego zasobu danych

IDXDesc

Deskryptor indeksu

IDXType

Deskryptor typu indeksu

LDDesc

Deskryptor sterownika języka

LOCKDesc

Deskryptor blokady

RECProps

Deskryptor własności rekordu

RINTDesc

Deskryptor integralności

SECDesc

Deskryptor ochrony

SESInfo

Deskryptor informacji o sesji

SPDesc

Deskryptor procedury standardowej

SPParamDesc

Deskryptor parametrów procedury standardowej

SYSConfig

Deskryptor informacji o konfiguracji systemu

SYSInfo

Deskryptor statusu systemu BDE

SYSVersion

Deskryptor informacji o wersji systemu BDE

TBLBaseDesc

Deskryptor informacji o tabeli podstawowej

TblExtDesc

Deskryptor informacji o tabeli dodatkowej

TBLFullDesc

Deskryptor informacji o tabeli pełnej

TBLType

Deskryptor możliwości tabeli

background image

Rozdzial 26 Borland Database Engine (BDE)

753

Struktura

Opis

USERDesc

Deskryptor użytkownika

VCHKDesc

Deskryptor sprawdzenia ważności

XInfo

Deskryptor transakcji

Oprócz tych struktur BDE definiuje obiekty podane w tabeli 26.2.

Tabela 26.2 Obiekty definiowane przez BDE

Obiekt

Typ

Opis

hDBICur hDBIObj

Uchwyt kursora

hDBIDb hDBIObj

Uchwyt bazy danych

hDBIObj UINT32

Uchwyt obiektu nieokreślonego

hDBIQry hDBIObj

Uchwyt zapytania

hDBISes hDBIObj

Uchwyt sesji

hDBIStmt hDBIObj

Uchwyt instrukcji zapytania

hDBIXact UINT32

Uchwyt transakcji

hDBIXlt hDBIObj

Uchwyt translacji

phDBICfg

^

hDBICfg

Wskaźnik uchwytu konfiguracji

phDBICur

^

hDBICur

Wskaźnik uchwytu kursora

phDBIDb

^

hDBIDb

Wskaźnik uchwytu bazy danych

phDBIObj

^

hDBIObj

Wskaźnik uchwytu nieokreślonego obiektu

phDBIQry

^

hDBIQry

Wskaźnik uchwytu zapytania

phDBISes

^

hDBISes

Wskaźnik uchwytu sesji

phdbistmt

^

hdbistmt

Wskaźnik uchwytu instrukcji

phDBIXact

^

hDBIXact

Wskaźnik uchwytu transakcji

phDBIXlt

^

hDBIXlt

Wskaźnik uchwytu translacji

Najczęściej w aplikacjach używane są zmienne:

hDBIDb

i

hDBICur

. Zmienna

hDBIDb

zwracana jest przy otwieraniu bazy danych,

hDBICur

- przy otwieraniu

tabeli. Odpowiada to właściwościom

DBHandle

i

Handle

tabel TDBDataSet

i TBDEDataSet.

background image

754

Część IV

Budowanie aplikacji BDE

Najprawdopodobniej nie będziemy autorami aplikacji, stworzonej wyłącznie przy
pomocy odwołań BDE (tj. z pominięciem komponentów bazodanowych Delphi).
Niemniej jednak wiedza o wymaganiach takiej aplikacji może być pożyteczna,
ponieważ pomaga zrozumieć procesy, w wyniku których Delphi zapewnia dostęp
do bazy danych. Aby stworzyć aplikacje stosując tylko odwołania BDE API,
powinniśmy wykonać 12 podstawowych kroków:

1. Zainicjować mechanizm BDE.

2. Ustawić warstwę analizy programu (debug layer).

3. Otworzyć bazę danych.

4. Ustawić katalog roboczy.

5. Ustawić katalog tymczasowy.

6. Otwierając tabelę stworzyć kursor.

7. Pobrać właściwości tabeli

8. Ulokować obszar bufora rekordu.

9. Przesunąć kursor na pożądany rekord.

10. Pobrać rekord z kursora.

11. Pobrać żądane pole z rekordu.

12. Zwolnić wszystkie przydziały zasobów.

Listing 26.1 ilustruje powyższe 12 kroków. W tym przykładzie dokonywana jest
konwersja aplikacji wzorcowej (pobranej z Helpa BDE) - z języka C na Object
Pascal. Po zakończeniu konwersji, aplikacja jest wstawiana do zdarzenia

OnClick

komponentu przycisku.

Listing 26.1. Aplikacja wzorcowa BDE Help przepisana w Object
Pascalu i

poddana konwersji na obsługę zdarzenia OnClick

przycisku.

{*******************************************************}
{

}

{ BDE Template Program

}

{

}

{ Copyright (c) 1996 Borland International

}

{

}

{*******************************************************}
{

Conversion to Object Pascal by Ken Henderson.

background image

Rozdzial 26 Borland Database Engine (BDE)

755

}
unit bdetemp;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs,

StdCtrls, ToolWin, ComCtrls, BDE;

type

TForm1 = class(TForm)

ToolBar1:

TToolBar;

Button1:

TButton;

procedure

Button1Click(Sender:

TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var
Form1:

TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var

hDb : hDBIDb; // Handle to the Database

hCur : hDBICur; // Handle to the cursor (table)

szTblName : String;

szTblType : String;

CursorProps : CURProps; // Properties of the cursor

pRecBuf : pBYTE; // Pointer to the record buffer

EmpNo : integer;

isBlank : BOOL;

function Chk(ErrorValue : DBIResult) : DBIResult;
var

dbi_status : string;

dbi_string : string;

ErrInfo : DBIErrInfo;

count : integer;

begin
dbi_status:=’’;
dbi_string:=’’;

if (ErrorValue <> DBIERR_NONE) then begin

DbiGetErrorInfo(TRUE,

ErrInfo);

background image

756

Część IV

if (ErrInfo.iError = ErrorValue) then begin

dbi_status:=’ ERROR ‘+ ErrInfo.szErrCode;

With

ErrInfo

do

for count:=low(szContext) to high(szContext) do

if

(strcomp(ErrInfo.szContext[count],

‘’)<>0) then

dbi_status

:=

dbi_status+’

‘+

ErrInfo.

szContext[count];

end

else

begin

SetLength(dbi_string,

DBIMAXMSGLEN);

DbiGetErrorString(ErrorValue,

PChar

(dbi_string));

dbi_status := ‘ ERROR ‘+dbi_string;

end;

MessageBox(0, PChar(dbi_status), ’BDE Error’, MB_OK

or MB_ICONEXCLAMATION);

end;
result:=ErrorValue;
end;

begin

hDb := nil;

hCur := nil;

ShowMessage(‘Initialize

engine’);

Chk(DbiInit(nil)); // Step 2

ShowMessage(‘Set debug layer options’);

DbiDebugLayerOptions(DEBUGON or OUTPUTTOFILE or

FLUSHEVERYOP, ‘TRACE.TXT’);// Step 3

ShowMessage(‘Open

database’);

Chk(DbiOpenDatabase(

//

Step

4

nil,

// Database name - nil for standard

database

nil,

// Database type - nil for standard

database

dbiREADWRITE,

// Open mode - Read/Write or Read only

dbiOPENSHARED,

// Share mode - Shared or Exclusive

nil,

// Password - not needed for the

STANDARD database

0,

//

Number

of

optional

parameters

nil,

// Field Desc for optional parameters

nil,

// Values for the optional parameters

hDb));

// Handle to the database

ShowMessage(‘Set table directory’);

background image

Rozdzial 26 Borland Database Engine (BDE)

757

Chk(DbiSetDirectory(

//

Step

5

hDb,

// Handle to the database which

is being modified

‘C:\Program Files\Borland\Delphi 3.0\Demos\Data’));

// The new working directory

ShowMessage(‘Set private directory’);

Chk(DbiSetPrivateDir(

// Step 6

‘c:\temp’));

// Select a directory on

a local drive not used

//

by

other

applications.

szTblName:=’EMPLOYEE’;
szTblType:=szPARADOX;
ShowMessage(‘Open

table’);

Chk(DbiOpenTable(

//

Step

7

hDb,

//

Handle

to

the

standard

database

PChar(szTblName),

// Name of the table

PChar(szTblType),

// Type of the table - only

used for local tables

nil,

//

Index

Name

-

Optional

nil,

//

IndexTagName

-

Optional.

Only used by dBASE

0,

//

IndexId

-

0

=

Primary.

dbiREADWRITE,

// Open Mode - Read/Write or

Read Only

dbiOPENSHARED,

// Shared mode - SHARED or EXCL

xltFIELD,

// Translate mode - Almost

always xltFIELD

FALSE,

//

Unidirectional

cursor

movement.

nil,

//

Optional

Parameters.

hCur));

//

Handle

to

the

cursor

ShowMessage(‘Get cursor properties’);

Chk(DbiGetCursorProps(

// Step 8

hCur,

//

Handle

to

the

cursor

CursorProps));

// Properties of the cursor

(table)

ShowMessage(‘Allocate a record buffer’);

GetMem(pRecBuf,CursorProps.iRecBufSize * sizeof(BYTE));

// Step 9

if (pRecBuf = nil) then

ShowMessage(‘Error

allocating

buffer’)

else

begin

background image

758

Część IV

ShowMessage(‘Set cursor to the crack before the

first record’);

Chk(DbiSetToBegin(hCur)); // Step 10

// Position the specified cursor to the crack

// before the first record

ShowMessage(‘Get the next record’);

Chk(DbiGetNextRecord(

// Step 11

hCur,

// Cursor from which to get the record.

dbiNOLOCK,

//

Lock

Type

pRecBuf,

// Buffer to store the record

nil));

// Record properties - don’t need in this case

ShowMessage(‘Get a field out of the record buffer’);

Chk(DbiGetField(

hCur,

// Cursor which contains the record

1,

// Field Number of the “EmpNo”

field.

pRecBuf,

// Buffer containing the record

@EmpNo,

//

Variable

for

the

EmpNo

isBlank));

// Is the field blank?

ShowMessage(‘The retrieved field

value is ‘+ IntToStr(EmpNo));

end;

ShowMessage(‘Clean-up’);

if (pRecBuf <> nil) then

freemem(pRecBuf); // Free the record buffer

if (hCur <> nil) then

Chk(DbiCloseCursor(hCur));

// Close the cursor

if (hDb <> nil) then

Chk(DbiCloseDatabase(hDb));

// Close the database

DbiExit;

//

Close

the

BDE.

end;

end.

background image

Rozdzial 26 Borland Database Engine (BDE)

759

Jak można zauważyć kod jest dołączany do przycisku zdarzenia

OnClick

na

formularzu Delphi. Kod ten można wpisać do własnego zdarzenia

OnClick

- by

sprawdzić jego działanie. Należy zauważyć, że moduł ten powoduje otwarcie
tabeli EMPLOYEE w katalogu:

C:\Program Files\Borland\Delphi

3.0 \Demos\Data

. W związku z tym należy zadbać, aby tabela ta zaistniała

przed uruchomieniem modułu.

W klauzuli

Uses

modułu należy odnotować wykorzystanie modułu BDE. Zawiera

wszystkie informacje o procedurach i typach danych dla mechanizmu bazy danych.
Aby były one dostępne bezpośrednio dla BDE należy dodać je do polecenia

Uses

.

Aczkolwiek większość twórców aplikacji Delphi nigdy nie buduje aplikacji, która
realizuje dostęp do bazy danych wyłącznie przy pomocy odwołań BDE API,
powyższy kod traktować możemy jako pewien szablon, przy pomocy którego
można tego dokonać.

Dostęp do BDE z aplikacji Delphi

Najbardziej prawdopodobny jest scenariusz zakładający, iż prawie cały dostęp do
bazy danych realizowany będzie przy pomocy wbudowanych komponentów
Delphi (z wykonywaniem niektórych specjalizowanych funkcji poprzez
bezpośrednie odwołania BDE). Ilustracją tego typu podejścia jest komponent

LiveQuery (

opisany szczegółowo w

rozdziale 27), stosujący - w

celu

wykonania zapytania w zdarzeniu

BeforeOpen

potomka

TTable

- funkcję

BDE

DBiQExecDirect

. Kod źródłowy podano w listingu 26.2.

Listing 26.2 Komponent LiveQuery wykorzystuje funkcję BDE

o nazwie DBiQExecDirect

(

Komponent Delphi LiveQuery

Obsługuje edycję zbiorów wynikowych servera SQL przy pomocy

tymczasowych perspektyw (views). Umożliwia to uaktualnienie

każdego modyfikowalnego zbioru wynikowego przez użytkownika,

który stworzył go jako perspektywę na serwerze. Dlatego

obsługiwane są wszystkie modyfikacje, które mogłyby być

obsługiwane przez serwer za pośrednictwem perspektyw.

Napisał Ken Henderson.

Copyright © 1995 by Ken Henderson

Kilka zastrzeżeń:

1) Sztuczka ta jest wykonywana przy pomocy tymczasowych

perspektyw i w

związku z

tym:

background image

760

Część IV

a)

Ponieważ pewne platformy, jak Sybase, nie obsługują

tym

czasowych perspektyw, musiałem skonstruować nazwę

tymczasową (temp name) oraz stworzyć i

opuścić

perspektywę. Nazwa powstała na podstawie daty i

czasu,

w

związku z

tym kolizje z

innymi użytkownikami są

praktycznie niemożliwe. Patrz kod źródłowy. Możliwa

jest obsługa ewentualnych wyjątków. Jeśli taka sytuacja

zdarzy się, ponownie wydawane jest polecenie Open ....

b)

Oczywiście twoi użytkownicy nadal będą potrzebowali

zezwolenia na tworzenie perspektyw.

c) Ponieważ komponent ten tworzy perspektywy, jest tyl

ko

użyteczny na serwerach, które je obsługują (tj.:

serwerach zdalnych) -

nie można go używać z

tabelami

dBASE i Paradox.

Po stronie korzyści:

1) Do opisu modyfikowalnych perspektyw możemy użyć dowolnej

składni, która jest obsługiwana przez komputer. Składnia ta

powinna zapewniać:

a) dowolną, żądaną liczbę tabel za pośrednictwem złączeń

b) klauzule (clauses)

Pozwoli to na ulokowanie całego obciążenia na serwerze, gdzie

moim zdaniem powinno się znajdować. Oznacza to także, że

wykonywane polecenia SQL będą najpierw kompilowane, co jest

bardziej efektywne. Jeśli serwer nie akceptuje modyfikacji

która ma być wykonana, wystąpi oczywiście wyjątek.

}

unit Liveqry;

interface

uses

SysUtils, WinTypes, WinProcs, Messages, Classes,

Graphics, Controls,

Forms, Dialogs, DB, DBTables, BDE;

const

DEFAULTCREATEVIEWSQL = ‘CREATE VIEW %s AS ‘;

DEFAULTDROPVIEWSQL = ‘DROP VIEW %s’;

DEFAULTTABLENAMEFORMAT = ‘TV%s’;

type

TLiveQuery = class(TTable)

private

{ Private declarations }

FCreateViewSQL

:

String;

FDropViewSQL

:

String;

background image

Rozdzial 26 Borland Database Engine (BDE)

761

FTableNameFormat

:

TFileName;

FSQL

:

TStrings;

procedure

SetQuery(Value:

TStrings);

protected

{ Protected declarations }

procedure

CreateTemporaryView;

procedure

DropTemporaryView;

procedure

DoBeforeOpen;

override;

procedure

DoAfterClose;

override;

public

{ Public declarations }

constructor Create(AOwner: TComponent); override;

destructor

Destroy;

override;

published

{ Published declarations }

property CreateViewSQL : String read FCreateViewSQL

write FCreateViewSQL;

property DropViewSQL : String read FDropViewSQL

write FDropViewSQL;

property SQL : TStrings read FSQL write SetQuery;

property TableNameFormat : TFileName read

FTableNameFormat write FTableNameFormat;

end;

procedure Register;

implementation

constructor TLiveQuery.Create(AOwner: TComponent);
begin
inherited

Create(AOwner);

FSQL := TStringList.Create;

FCreateViewSQL := DEFAULTCREATEVIEWSQL;

FDropViewSQL := DEFAULTDROPVIEWSQL;

FTableNameFormat := DefaultTableNameFormat;

end;

destructor TLiveQuery.Destroy;
begin

If Active then begin

Close;
DropTemporaryView;
end;
SQL.Free;
inherited

Destroy;

end;

procedure TLiveQuery.SetQuery(Value: TStrings);
begin
CheckInActive;

background image

762

Część IV

SQL.Assign(Value);
end;

procedure TLiveQuery.CreateTemporaryView;
var

TemporaryDB : TDatabase;

WorkSQL : TStrings;

begin

WorkSQL := TStringList.Create;

WorkSQL.AddStrings(SQL);
TableName:=Format(TableNameFormat,[FormatDateTime(‘yymmdd

hhnnss’,Now)]);

WorkSQL.Insert(0,Format(CreateViewSQL,[TableName]));
TemporaryDB:=Session.OpenDatabase(DatabaseName);

If (TemporaryDB<>nil) then

try

If (TemporaryDB.IsSQLBased) then begin

If

(DbiQExecDirect(TemporaryDB.

Handle,qrylangSQL,

PChar(WorkSQL.Text),nil)<>DBIERR_NONE)

then

raise

EDatabaseError.Create(‘Error

creating

temporary view’);

end

else

raise EDatabaseError.Create(‘Cannot use this

component with local tables’)

finally
Session.CloseDatabase(TemporaryDB);
WorkSQL.Free;
end;
end;

procedure TLiveQuery.DoBeforeOpen;
begin
inherited

DoBeforeOpen;

CreateTemporaryView;
end;

procedure TLiveQuery.DropTemporaryView;
var

TemporaryDB : TDatabase;

WorkSQL : TStrings;

begin
try
WorkSQL:=TStringList.Create;
WorkSQL.Add(Format(DropViewSQL,[TableName]));
TemporaryDB:=Session.OpenDatabase(DatabaseName);

If (TemporaryDB<>nil) then begin

If (TemporaryDB.IsSQLBased) then begin

background image

Rozdzial 26 Borland Database Engine (BDE)

763

If

(DbiQExecDirect(TemporaryDB.Handle,

qrylangSQL, PChar(WorkSQL.Text),nil)

<>DBIERR_NONE) then

raise

EDatabaseError.Create(‘Error

dropping

temporary view’);

end

else

raise EDatabaseError.Create(‘Cannot use this

component with local tables’)

finally
Session.CloseDatabase(TemporaryDB);
WorkSQL.Free;
end;
end;
end;

procedure TLiveQuery.DoAfterClose;
begin
DropTemporaryView;
inherited

DoAfterClose;

end;

procedure Register;
begin

RegisterComponents(‘Data Access’, [TLiveQuery]);

end;

end.

Zwróćmy uwagę na funkcję

DBiQExecDirect

. Zaraz po zbudowaniu procedurą

polecenia SQL

WorkSQL

, jest ono gotowe do przetworzenia. Z uwagi na fakt, iż

stosowany jest komponent potomny

Table

, nie ma prostej możliwości realizacji

utworzonego wyrażenia SQL. Jeśli

LiveQuery

był potomkiem komponentu

Query, wówczas możliwy byłby dostęp do procedury ExecSQL (ale tak nie jest).
Tak dzieje się, gdy w

grę wchodzi funkcja

DBiQExecDirect

. W celu

wykonania zapytania SQL tworzony jest tymczasowy obiekt

hDBIDb

, przesyłany

następnie, wraz z zawartością WorkSQL, do funkcji

DBiQExecDirect

.

UWAGA

Jeśli nie osiągnięto zgodności z Serwerem SQL, wtedy - zamiast tymczasowego
połączenia bazy danych (które zostało stworzone przez komponent) - możemy
skorzystać z własności

DBHandle

komponentu

LiveQuery

. Serwer zakazuje

inicjowania nowego zapytania w czasie, gdy wyniki poprzedniego zapytania
pozostają nierozstrzygnięte - stąd stosowanie

LiveQuery.Database.Handle

z funkcją

DBiQExecDirect

w środowisku SQL Serwer nie ma uzasadnienia.

background image

764

Część IV

Należy zauważyć, że trzeci parametr funkcji

DbiQExecDierct

wymaga typu

danych

PChar

. Łańcuchy

Pchar

stanowią pascalową wersję łańcucha

char

*

w C i C++. Począwszy od Delphi 2.0, translacja łańcuchów pascalowych na
łańcuchy C/C++ ogranicza się do ich wpisania. Łańcuchy pascalowe są teraz
zakończone pustym znakiem (NULL) i twórcy aplikacji także tym nie muszą się
martwić. Co więcej - łańcuchy w Pascalu także zawierają pole długości, dzięki
czemu nie trzeba przeszukiwać łańcucha (ze względu na pusty znak) - by odczytać
ich długość, jak dzieje się to w przypadku języka C.

Wykonywanie odwołań do DBMS

BDE umożliwia również dostęp do bezpośredniej obsługi dla konkretnego DBMS.
Taka właściwość pozwala na wykonanie odwołań do funkcji w bibliotekach
klienta danego DBMS, z całkowitym pominięciem komponentów baz danych
Delphi i BDE. W pewnych okolicznościach poprawi to wydajność, umożliwiając
ponadto funkcjonalne pominięcie BDE.

Do pobrania uchwytu połączenia rodzimego do danej DBMS należy użyć funkcji

DbiGetProp.

W tabeli 26.3 zebrano typy informacji, dostępne na każdej platformie.

Tabela 26.3 Informacje platformy DBMS zwracane przez

DbiGetProp.

Platforma

Typ uchwytu

Długość

InterBase

gds_db_handle

4

Sybase

DBPROCESS NEAR *

2

Oracle

LDA

64

ODBC Socket

HDBC

4

Poniższy fragment kodu zawiera pewien przykład składni, której można użyć na
platformie Sybase - by pobrać nazwy aktualnej bazy danych:

type

DBPROCESS = Pointer;

var

Form1: TForm1;

DBProc: DBPROCESS;

Size DBProc: Word;

function dbname(DBOros: DBPROCESS) : Pchar; external

‘LIBSYBDB’;

background image

Rozdzial 26 Borland Database Engine (BDE)

765

implementation

{$R *.DFM)

Procedure TForm1.Button1Click(sender: Tobject);
begin

biGetProp(hDBiObj (Table1.DBHandle),dbNATIVEHNDL,

DBProc, SizeOf(DBProc), SizeDBProc;

Edit1.Text:=dbname(DBProc);
end;

W tym przykładzie funkcja

dbname

z biblioteki DB-Library jest odnoszona

zewnętrznie w

LIBSYBDB DLL. Takie połączenie wymaga pojedynczego

parametru bieżącego połączenia uchwytu DBPROCESS. Uchwyt ten jest
pobierany poprzez wywołanie

DbiGetProp i

przekazywany następnie do

parametru

dbNATIVEHNDL

.

Pobieranie informacji charakterystycznych dla danej
platformy poprzez BDE

Jeśli zamiarem twórcy aplikacji jest umożliwienie użytkownikowi budowania
zapytań podczas wykonania programu, wówczas należy zapewnić sobie - na
wybranej platformie DBMS - możliwość listowania nie tylko tabel i kolumn, ale
także funkcji, które platforma obsługuje podczas zapytania o dane. Koniecznym
może okazać się wyświetlanie takich elementów, jak łańcuchy, dane i funkcje
numeryczne itd. Funkcją BDE, realizującą powyższe zadania, jest

DbiOpenFunctionList

. Otwiera ona kursor w liście funkcji obsługiwanej

przez skojarzoną platformę DBMS. Aby pobrać kolejno każdą obsługiwaną nazwę
funkcji należy wywołać

DBiGetNextRecord

. Listingi 26.3 do 26.5 ilustrują

prosty program Delphi, wykorzystujący - do listowania tabeli obiektów obecnych
na aktualnej platformie DBMS oraz funkcji obsługiwanych przez platformę -
funkcję

DbiOpenFunctionList

Program przedstawia listę rozwijalną aliasów BDE, które można wybrać i zapytać
o informacje dotyczące funkcji i tabeli.

Listing 26.3 Plik źródłowy projektu dla programu

przykładowego funkcji BDE DbiOpenFunctionList,

FuncEx.

program funcex;

uses
Forms,

funcex

∅∅

in 'funcex

∅∅

.pas' {Form1};

{$R*.RES}

background image

766

Część IV

begin
Application.Initialize;

Application.CreateForm(TForm1,

Form1);

Applicatiob.Run;
end.

Listing 26.4 Plik źródłowy modułu dla FuncEx00.PAS, tylko

moduł w

programie przykładowym BDE DbiOpenFunctionList,

FuncEx.

unit funcex00;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics, Controls,

Forms, Dialogs, DBTables, StdCtrls, BDE;

type

TForm1 = class(TForm)

Label1:

TLabel;

Label2:

TLabel;

Label3:

TLabel;

ListBox1:

TListBox;

ComboBox1:

TComboBox;

ListBox2:

TListBox;

Database1:

TDatabase;

procedure

ComboBox1Change(Sender:

TObject);

procedure

FormCreate(Sender:

TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var
Form1:

TForm1;

implementation

{$R *.DFM}

procedure TForm1.ComboBox1Change(Sender: TObject);

function Chk(ErrorValue : DBIResult) : DBIResult;
var

dbi_status : string;

dbi_string : string;

ErrInfo : DBIErrInfo;

count : integer;

background image

Rozdzial 26 Borland Database Engine (BDE)

767

begin
dbi_status:=’’;
dbi_string:=’’;

if (ErrorValue <> DBIERR_NONE) then begin

DbiGetErrorInfo(TRUE,

ErrInfo);

if (ErrInfo.iError = ErrorValue) then begin

dbi_status:=’ ERROR ‘+ ErrInfo.szErrCode;

With

ErrInfo

do

for count:=low(szContext) to high(szContext) do

if

(strcomp(ErrInfo.szContext[count],

‘’)<>0) then

dbi_status

:=

dbi_status+’

‘+

ErrInfo.szContext[count];

end

else

begin

SetLength(dbi_string,

DBIMAXMSGLEN);

DbiGetErrorString(ErrorValue,

PChar(dbi_string));

dbi_status := ‘ ERROR ‘+dbi_string;

end;

MessageBox(0, PChar(dbi_status), ‘BDE Error’, MB_OK

or MB_ICONEXCLAMATION);

end;
result:=ErrorValue;
end;

var

hCur : hDBiCur;

FuncInfo : DBiFUNCDESC;

Counter : integer;

begin

With Database1 do begin

Connected:=False;
ListBox2.Items.Clear;
DatabaseName:=ComboBox1.Items[ComboBox1.ItemIndex];
Open;
Session.GetTableNames(DatabaseName,’’,False,

False,

ListBox1.Items);

end;
counter:=0;

If (Chk(DbiOpenFunctionList(Database1.Handle, [ic:ccc}

fnListINCL_USER_DEF, @hcur)) = DBIERR_NONE) then begin

if (hCur<>nil) then begin

while

(DBiGetNextRecord(hCur,dbinolock,@FuncInfo,

nil)<>DBIERR_EOF) and (counter <50) do begin

ListBox2.Items.Add(FuncInfo.szName);
inc(counter);
end;

background image

768

Część IV

DbiCloseCursor(hCur);
ListBox2.Sorted:=True;

end else ShowMessage(‘Error opening cursor’);

end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Session.GetDatabaseNames(ComboBox1.Items);
ComboBox1.ItemIndex:=0;
end;

end.

Listing 26.5 Plik formularza (.DFM) dla FuncEx00.PAS,

pojedynczy moduł w

programie przykładowym BDE

DbiOpenFunctionList, FuncEx.

object Form1: TForm1

Left = 200

Top = 108

Width = 544

Height = 375

Caption = ‘Form1’

Font.Color = clWindowText

Font.Height = -11

Font.Name = ‘MS Sans Serif’

Font.Style = []

OnCreate = FormCreate

PixelsPerInch = 96

TextHeight = 13

object Label1: TLabel

Left

=

33

Top

=

0

Width

=

36

Height

=

13

Caption

=

‘Aliases:’

end

object Label2: TLabel

Left

=

32

Top

=

40

Width

=

35

Height

=

13

Caption

=

‘Tables:’

end

object Label3: TLabel

Left

=

216

Top

=

40

Width

=

98

Height

=

13

Caption = ‘Supported functions:’

end

background image

Rozdzial 26 Borland Database Engine (BDE)

769

object ListBox1: TListBox

Left

=

32

Top

=

56

Width

=

177

Height

=

209

ItemHeight

=

13

TabOrder

=

0

end

object ComboBox1: TComboBox

Left

=

32

Top

=

14

Width

=

177

Height

=

21

Style

=

csDropDownList

ItemHeight

=

13

TabOrder

=

1

OnChange

=

ComboBox1Change

end

object ListBox2: TListBox

Left

=

216

Top

=

56

Width

=

177

Height

=

209

ItemHeight

=

13

TabOrder

=

2

end

object Database1: TDatabase

DatabaseName

=

‘DBDEMOS’

SessionName

=

‘Default’

Left

=

496

end
end

background image

770

Część IV

Indeksy wyrażeniowe

Jedna z największych korzyści wynikających z faktu, że BDE obsługuje indeksy
oparte na wyrażeniach dBASE jest to, że wywodzący się z dBASE mechanizm
obliczania wartości (ewaluator) wyrażeń możemy wykorzystać we własnych
aplikacjach. Pozwala to na włączenie ewaluatora wyrażeń, wraz z bogactwem
indeksów dBASE, do aplikacji Delphi. Ewaluator obsługiwałby wyrażenia
zawierające wszystkie operacje i funkcje dostępne w indeksach dBASE.

Aby uzyskać dostęp do ewaluatora wyrażeń BDE należy stworzyć indeks
wyrażeniowy w oparciu o fikcyjną tabelę DBF dBASE. W tym celu powinniśmy
utworzyć jednowierszową tabelę dBASE (struktura nie ma znaczenia) oraz
umożliwić aplikacji wprowadzenie wyrażenia (które nie musi operować na tabeli).
Tabelę użyjemy tylko do stworzenia indeksu - by obliczyć wyrażenie. Gdy
wyrażenie jest wprowadzane do aplikacji, należy stworzyć indeksowanie tabeli na
bazie wprowadzonego wyrażenia (jako klucza). Wystarczy wówczas przełączyć
nowy indeks tak, aby stał się bieżącym indeksem tabeli i - wykorzystując funkcję
BDE

DbiExtractKey

- powrócić do głównej (lub obliczonej) wartości klucza..

Poniżej przedstawiliśmy fragment kodu z aplikacji stosującej opisaną technikę.

procedure TForm1.Button1Click(Sender: TObject);
var

IndexDesc : IDXDesc;

KeyString : String;

begin

Rysunek 26.1
Aplikacja FuncEX
pokazuje tabele
i funkcje dostępne
na platformie
DBMS.

background image

Rozdzial 26 Borland Database Engine (BDE)

771

With Table1 do begin

If not Active then Open;

AddIndex('EXPEVAL',Edit.Text,[ixExpression]);
Close

IndexName:='EXPEVAL';
Open;

DbiGetIndexDesc(Table1.Handle,

,IndexDesc);

SetLenght(KeyString,IndexDesc.iKeyLen);
DbiExtractKey(Tablee1.Handle,

nil,

PChar(KeyString));

Edit2.Text:=KeyString;

Close;
DeleteIndex('EXPEVAL');
IndexName:='DUMMY';
end;

end;

Najważniejsza jest tutaj procedura

DbiExtractKey

, która zwraca poddaną

translacji lub wyliczoną - na podstawie indeksu. - wartość klucza Ta pożyteczna
właściwość umożliwia dodanie do skompilowanej aplikacji Delphi
przypominającego interpreter narzędzia, pozwalającego wyliczyć wartość
wyrażenia. Na rysunku 26.2 przedstawiono aplikację, wykorzystującą funkcję

DbiExtract

do obliczenia wyrażenia złożonego.

Rysunek 26.2.
Aplikacja
z mechanizmem
kalkulacji wyrażeń
- funkcjąi BDE
DbiExtractKey

background image

772

Część IV

Optymalizacja BDE

Optymalizacja BDE może być trudnym procesem. Wskazówki podane poniżej nie
stanowią "cudownego leku", ale pozwalają ocenić, czy mechanizm jest
dostatecznie szybki (i czy nie wymaga dodatkowej kosmetyki).

„Modyfikacje danych są spowalniane przez liczne indeksy zewnętrzne.

W związku z tym należy ograniczyć je do niezbędnych. Może okazać się, że
będzie szybciej opuścić indeksy i przebudować je po wstawieniu danych.

„Tabele powinniśmy otwierać jedynie w trybie wyłącznego dostępu.

„W miarę możliwości unikać manipulowania wierszami - lepiej operować na

porcjach BDE.

„Stosując funkcję

DbiWriteBlock

powinniśmy starać się pracować

z blokami fizycznymi o różnej wielkości.

„Funkcji

DbiAcqPersistTableLock

można użyć w stosunku fikcyjnej

tabeli - by wymusić stworzenie pliku .

LCK

, który - przy otwieraniu i zamykaniu

tabel - nie byłby kasowany i ponownie tworzony w trakcie otwierania
i zamykania tabel.

„Należy używać tabel tworzonych w pamięci operacyjnej, a nie na dysku

twardym. Nie wolno nam jednak zapominać o tym, iż tabel przechowywanych
w pamięci operacyjnej nie można indeksować, kopiować lub zapisywać
w sposób trwały.

Optymalizacja dostępu BDE do SQL

Optymalizacja SQL-a została omówiona dokładniej w rozdziale 24 i 25. W tym
miejscu ograniczyliśmy się do kilku ogólnych wskazówek związanych z dostępem
BDE do SQL.

„Wykonując serię modyfikacji na serwerze SQL, należy stosować transakcje

jawne, unikając rozpoczynania i kończenia transakcji niejawnych dla każdej
modyfikacji.

„Przygotować złożone zapytania i procedury pamiętane dla bezpośrednich

odwołań SQL (PassThrough SQL). W rezultacie BDE dostarczy, możliwie
najszybciej, nasze zapytania SQL do serwera, pozwalając nam na stosowanie
dowolnego SQL, wspieranego przez mechanizmy serwera.

„Jak już wspominaliśmy, istnieje możliwość - dzięki informacjom przekazanym

przez funkcję IDAPI

DbiGetProps

- realizacji wywołań rodzimych dla

DBM.

background image

Rozdzial 26 Borland Database Engine (BDE)

773

„Wykonać pierwszy człon zapytania, co pozwoli zmniejszyć jego zbiór

wynikowy - a po zredukowaniu (w maksymalnym stopniu) zestawu wyników -
grupowanie lub złączenie .

„W pewnych przypadkach zalecane jest kopiowanie wyników zapytania do

lokalnej tabeli.

„Funkcje

DbiAddFilter

,

DbiSetRange

i

DbiSetFieldMap

pomagają

zredukować ilość aktualnie dostępnych danych. Efektem każdorazowej redukcji
danych pierwotnych (przeznaczonych do przetwarzania) będzie przyspieszenie
pracy aplikacji. Zauważmy, że wszystkie te właściwości obsługiwane są
bezpośrednio przez kontrolki Delphi DataSet

„Tworzenie indeksów zstępujących dla tabel, na których wykonywane jest

często przewijanie wsteczne, pozwala istotnie zaoszczędzić czas pracy serwera.

„Gdy znajdujemy się w środku dużej tabeli lub jeśli tabela zawiera indeks

złożony, powinniśmy unikać stosowania

DbiSetToEnd

i

DbiSetToKey.

Wywołanie tych funkcji w nieodpowiednim momencie może spowodować
sekwencyjne przeglądanie przez aplikację znacznej liczbę wierszy.


Wyszukiwarka

Podobne podstrony:
27 rozdzial 26 mjtwzr7c54hzzud5 Nieznany
26 rozdzial 25 nealxkacg62juqze Nieznany
26 rozdzial 25 PK6QXDXOCBYMLC6T Nieznany (2)
26 27 ROZ w spr ustalania g Nieznany (2)
Rozdział 26 27 z
05 rozdzial 04 nzig3du5fdy5tkt5 Nieznany (2)
egzamin 2 termin 27 06 2005 id Nieznany
22 Rozdzial 21 KP4Q5YBIEV5DBSVC Nieznany (2)
09 08 Rozdzielnice budowlane RB Nieznany (2)
17 rozdzial 16 fq3zy7m2bu2oan6t Nieznany (2)
Kanicki Systemy Rozdzial 10 id Nieznany
29 rozdzial 28 ciw47mwstcqakqpq Nieznany
24 rozdzial 23 wjv3mksbkbdm37qy Nieznany
29 rozdzial 28 w3cbrpnwzh762znr Nieznany (2)
13 Rozdziae 12id 14782 Nieznany (2)
27 Samotnosc, powolanie, rozez Nieznany
16 rozdzial 15 EJCDLTJY3F3I2FKL Nieznany (2)
14 rozdzial 13 w2pa42u4da5r3dcm Nieznany (2)

więcej podobnych podstron