作為一個ASP愛好者,筆者經(jīng)常在ASP頁面中使用ADO對象操作ODBC數(shù)據(jù)庫,覺得用ASP創(chuàng)建Web應(yīng)用系統(tǒng)確實是挺方便的。雖然在編程生涯中,筆者更喜歡Borland系列產(chǎn)品,對微軟產(chǎn)品有點排斥,但對ASP卻是例外。某天,忽然想到,ADO對象是一個標(biāo)準(zhǔn)OLE對象,如果在Delphi應(yīng)用程序中能利用ADO操作數(shù)據(jù)庫,應(yīng)該挺不錯。尤其在用DELPHI做網(wǎng)絡(luò)數(shù)據(jù)庫應(yīng)用程序時,如果所在的Web站點是WINNT站點并且支持ASP頁面,那就可以用ADO對象訪問ODBC數(shù)據(jù)庫,而不用把那么大的BDE再上載到站點上去。這樣就可充分利用DELPHI和ASP的編程優(yōu)勢,做出更好的ISAPI/NSAPI/CGI。經(jīng)過編程和測試,在Delphi中可以成功地用ADO對象存取ODBC數(shù)據(jù)庫,現(xiàn)將本人的使用經(jīng)驗寫出來,與大家共享,讓我們多一個訪問ODBC數(shù)據(jù)庫的方法。
在32位的Delphi中,可以聲明一個variant變量(如AVariant),然后通過CreateOleObject創(chuàng)建一個OLE對象,如AVariant:=CreateOleObject (’ADODB.Connection’)可以獲得一個數(shù)據(jù)庫連接對象的實例,然后就可以利用該對象的方法和屬性來操作ODBC數(shù)據(jù)庫了。 下面簡單介紹一下訪問ODBC數(shù)據(jù)庫所用到的ADO對象及其方法和屬性。
1、數(shù)據(jù)庫連接對象(ADODB. Connection) 該對象用于與ODBC數(shù)據(jù)庫建立連接,所有對數(shù)據(jù)庫的操作均通過該連接進(jìn)行。 數(shù)據(jù)庫連接對象ADODB. Connection的作用象Delphi中的TDatabase對象。 建立一個連接對象的方法為(AConnection為Variant類型變量): AConnection:=CreateOleObject(’A DODB.Connection’) 用于建立連接的方法為Open,使用語法為(以對象AConnection為例): AConnection.Open( ConnectionString, UserId, Password ) 三個參數(shù)均為字符串類型,其中UserId和Password為用戶名稱和用戶密碼,用于訪問數(shù)據(jù)庫使用時可以省略,因為在ConnectionString同樣可以指定用戶名稱和用戶密碼。ConnectionString是用來說明ODBC數(shù)據(jù)源信息的字符串,其格式為: ’Provider=ProviderName; DSN=DSNName; DRIVER=driver; SERVER=server; DATABASE=database; UID=user; PWD=password’ 其中: Provider:數(shù)據(jù)提供者,默認(rèn)狀態(tài)下為MSDASQL,為微軟OLEDB,通常省略; DSN:要打開的數(shù)據(jù)庫對應(yīng)的OBDC系統(tǒng)數(shù)據(jù)源(DSN),是可選參數(shù); DRIVER:要打開的數(shù)據(jù)庫所用的驅(qū)動程序名稱,如Access對應(yīng)Microsoft Access Driver (*.mdb),是可選參數(shù); SERVER:要打開的數(shù)據(jù)庫所在的服務(wù)器名稱,本機可用(local),是可選參數(shù); DATABASE:要打開的數(shù)據(jù)庫名稱,是可選參數(shù); UID:用戶名稱,用來訪問數(shù)據(jù)庫,是可選參數(shù); PWD:用戶密碼,用來訪問數(shù)據(jù)庫,是可選參數(shù)。 以上參數(shù)均為可選參數(shù),但必須提供足夠的信息來描述一個系統(tǒng)數(shù)據(jù)源。 假如已經(jīng)定義了一個ODBC的系統(tǒng)DSN,名稱為MyDsn,那么就可用以下語句建立一個數(shù)據(jù)庫連接: AConnection.Open(’DSN=MyDsn’); 為了防止DSN不存在或其設(shè)置被他人修改時造成應(yīng)用程序運行錯誤,可以用ADODB.Connection 創(chuàng)建一個臨時ODBC數(shù)據(jù)源,這樣可以保證我們使用的系統(tǒng)DSN的參數(shù)設(shè)置是正確的。下面的語句可以創(chuàng)建一個臨時ODBC系統(tǒng)DSN,對應(yīng)一個ACCESS數(shù)據(jù)庫,路徑為C:\Inetpub\ wwwroot\ test.mdb: AConnection.open(’Driver= {Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub \wwwroot\test.mdb’) 建立一個ADODB.Connection后,如果不需要返回操作結(jié)果(如刪除,修改,更新等操作)就可以對數(shù)據(jù)庫進(jìn)行正常的SQL操作了,此時應(yīng)用ADODB.Connection的另外一個方法Execute,使用語法為: AConnection.Execute( strSQL ); 其中strSQL為執(zhí)行操作的SQL語句,如刪除操作可以為:delete from wfjcommu。用AConnection.Close關(guān)閉一個數(shù)據(jù)庫連接。
2、數(shù)據(jù)集對象(ADODB. RecordSet) 如果要執(zhí)行查詢操作并返回查詢結(jié)果,或者要更方便地操作數(shù)據(jù)表,那就需要用到數(shù)據(jù)集對象了。 數(shù)據(jù)集對象ADODB.RecordSet的作用象Delphi中的TTable或TQuery對象。 建立一個數(shù)據(jù)集對象的方法為(ARecordSet為Variant類型變量): ARecordSet:=CreateOleObject (’ADODB.RecordSet’) 從數(shù)據(jù)表取得數(shù)據(jù)的方法為Open方法,具體使用方法為: ARecordSet.Open( strCommand,ActiveConnection,int CursorType,intLockType, intCommandType ); 其中: strCommand:字符串,為命令參數(shù),可以是一個Table名稱,可以是一個SQL語句,也可以是一個服務(wù)器上的存儲過程(StoredProc)名稱,具體需要后面的參數(shù)intCommandType來指定。 ActiveConnection:要使用的數(shù)據(jù)庫連接,是一個ADODB. Connection對象。 intCursorType:長整數(shù),數(shù)據(jù)集的Cursor類型,可選參數(shù),請參見程序中注釋。 intLockType:長整數(shù),對數(shù)據(jù)表的加鎖類型,可選參數(shù),請參見程序中注釋。 intCommandType:長整數(shù),命令參數(shù)的類型,用來指明strCommand的作用,可以指定strCommand為命令(如SQL語句)或數(shù)據(jù)表(TTable)或儲存過程(StoredProc),可選參數(shù),請參見程序中注釋。 如執(zhí)行一個SQL查詢,可以采用如下語句: ARecordSet.Open(’Select * from wfjcommu’,adOpenStatic,ad LockOptimistic,adCmdText); 其它常見屬性和方法與TTable和TQuery相比較如下(具體請見ASP幫助文件): eof,bof: eof,bof.MoveFirst, MoveLast: First, LastMovePrevious, MoveNext: Prior, NextMove: MoveByAddNew: appendUpdate: PostClose: close Delete加Update:delete,所有對數(shù)據(jù)表的修改均須用Update使操作有效,這與Delphi不同。 Fields[FieldNo]: Fields[FieldNo] Fields[’FieldName’]: FieldByName(’FieldName’)
3、其他常見對象(與Delphi對應(yīng)的對象): ADODB.Field: TField ADODB.Parameter: TPara ADODB.Error: EDBEngineError ADODB.Command:無 ADODB.Property:無 下面來看一個應(yīng)用例子: procedure TForm1.Button1Click(Sender: TObject); {***************************************************** 用ADO操作ODBC數(shù)據(jù)庫 本程序中,將創(chuàng)建一個臨時的ODBC系統(tǒng)數(shù)據(jù)源,指向一個MsAccess數(shù)據(jù)庫,然后對其中的數(shù)據(jù)表進(jìn)行顯示、增加、修改、刪除和查詢操作 注意:請在Uses語句中包含ComObj單元 *****************************************************} const{一些常量聲明,詳細(xì)請參見adovbs.inc} {---- CommandType的常量說明 ----} adCmdUnknown = 0008;//未知,需要系統(tǒng)來判斷,速度慢,為缺省值 adCmdText = 0001;//命令語句如SQL語句 adCmdTable = 0002;//數(shù)據(jù)表名稱 adCmdStoredProc = 0004;//存儲過程名稱
{---- CursorType的常量說明 ----} adOpenForwardOnly = 0;//只能由前向后單向訪問,為缺省值 adOpenKeyset = 1;//可見其他用戶對數(shù)據(jù)的修改,但對其它用戶的增加和刪除不可見 adOpenDynamic = 2;//其他用戶對數(shù)據(jù)的增加修改和刪除均可見 adOpenStatic = 3;//其他用戶對數(shù)據(jù)的增加修改和刪除均不可見
{---- LockType的常量說明 ---} adLockReadOnly = 1;//只讀,為缺省值 adLockPessimistic = 2;//在修改時,按單個記錄鎖定 adLockOptimistic = 3;//在修改后更新時,按單個記錄鎖定 adLockBatchOptimistic = 4;//在成批更新時記錄鎖定 var AConnection, ARecordSet : variant; longintTemp : integer; strTemp : string; intIndex : integer; begin {創(chuàng)建一個臨時的ODBC數(shù)據(jù)源,指向一個MsAccess數(shù)據(jù)庫,并利用此DSN建立一個數(shù)據(jù)庫連接} AConnection := CreateOleObject(’ADODB.Connection’); AConnection.Open(’Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\test’);
{建立一個數(shù)據(jù)集對象,并從數(shù)據(jù)表中提取數(shù)據(jù)} ARecordSet := CreateOleObject(’ADODB.RecordSet’); ARecordSet.open( ’wfjcommu’,AConnection,adOpenStatic,adLockOptimistic,adCmdTable );
memo1.lines.clear; memo1.lines.add(’********數(shù)據(jù)表原有的內(nèi)容如下********’); {顯示各個域的域名} strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].name+’;’; memo1.lines.add( strTemp );
{顯示各個域的內(nèi)容} while not ARecordSet.eof do begin strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].value+’;’; memo1.lines.add( strTemp ); ARecordSet.MoveNext;//移到下條,Next end;
{增加一個記錄} ARecordSet.AddNew;//增加,Append ARecordSet.Fields[’AName’] := ’1’;//以FieldByName的方式存取 ARecordSet.Fields[’Portable’] := ’2’; ARecordSet.Fields(2) := ’3’;//以Fields[index]的方式存取 ARecordSet.Fields(3) := ’4’; ARecordSet.Fields(4) := ’5’; ARecordSet.Update;//更新,Post ARecordSet.MoveFirst;//移到首條,F(xiàn)irst memo1.lines.add(’********增加了一條記錄后的數(shù)據(jù)表的內(nèi)容如下********’); {顯示各個域的內(nèi)容} while not ARecordSet.eof do begin strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].value+’;’; memo1.lines.add( strTemp ); ARecordSet.MoveNext;//移到下條,Next end;
{修改最后一條記錄} ARecordSet.MoveLast; ARecordSet.Fields[’AName’] := ’11’;//以FieldByName的方式存取 ARecordSet.Fields[’Portable’] := ’22’; ARecordSet.Fields(2) := ’33’;//以Fields[index]的方式存取 ARecordSet.Fields(3) := ’44’; ARecordSet.Fields(4) := ’55’; ARecordSet.Update;//更新,Post ARecordSet.MoveFirst;//移到首條,F(xiàn)irst memo1.lines.add(’********修改了最后一條記錄后的數(shù)據(jù)表的內(nèi)容如下********’); {顯示各個域的內(nèi)容} while not ARecordSet.eof do begin strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].value+’;’; memo1.lines.add( strTemp ); ARecordSet.MoveNext;//移到下條,Next end;
{刪除最后一條記錄} ARecordSet.MoveLast;//移到末條,Last ARecordSet.delete;//刪除,delete ARecordSet.Update;//更新,在Delphi不需要 ARecordSet.MoveFirst;//移到首條,F(xiàn)irst memo1.lines.add(’********刪除了最后一條記錄后的數(shù)據(jù)表的內(nèi)容如下********’); {顯示各個域的內(nèi)容} while not ARecordSet.eof do begin strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].value+’;’; memo1.lines.add( strTemp ); ARecordSet.MoveNext;//移到下條,Next end;
ARecordSet.Close;{關(guān)閉數(shù)據(jù)集}
{用SQL語句進(jìn)行查詢,查詢姓名為“張三”的記錄} {注意,在SQL語句中,字符串應(yīng)該用單引號包括起來} ARecordSet.open( ’select * from wfjcommu where AName = ’’張三’’’, AConnection,adOpenStatic,adLockOptimistic,adCmdText ); memo1.lines.add(’********張三的內(nèi)容如下********’); memo1.lines.add( ’共有’ + IntToStr( ARecordSet.RecordCount ) + ’條匹配的記錄’ ); {顯示各個域的內(nèi)容} while not ARecordSet.eof do begin strTemp := ’’; for intIndex := 0 to ARecordSet.Fields.count - 1 do strTemp := strTemp + ARecordSet.Fields[intIndex].value+’;’; memo1.lines.add( strTemp ); ARecordSet.MoveNext;//移到下條,Next end;
{關(guān)閉數(shù)據(jù)集和數(shù)據(jù)庫連接} ARecordSet.close; AConnection.close; end; 聽別人說總不如自己看實際的例子來體會。在這個例子中,將演示如何利用ADO對象來對一個數(shù)據(jù)表進(jìn)行查詢、增加記錄、修改記錄和刪除記錄操作。具體的用法請參見程序中的注釋,如果有點Delphi數(shù)據(jù)庫編程經(jīng)驗,相信不難理解。 在我們的例子使用的數(shù)據(jù)庫為Test.MDB,其中有一個數(shù)據(jù)表為wfjcommu,有五個字段AName、Portable、Tel、BP、PostAddress,分別表示姓名、手機號、電話號碼、呼機號碼和通信地址。 以上程序在PWIN98+ Delphi 3.0+PWS(Personal Web Server)4.0下調(diào)試通過.
|