用VB與RDO訪問(wèn)SQL Server
發(fā)表時(shí)間:2023-08-17 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]RDO的發(fā)展 遠(yuǎn)程數(shù)據(jù)對(duì)象 (Remote Data Object ,簡(jiǎn)稱RDO) 是位于 ODBC API 之上的一個(gè)對(duì)象模型薄層,它依賴 ODBC API、選定的 ODBC 驅(qū)動(dòng)程序以及后...
RDO的發(fā)展
遠(yuǎn)程數(shù)據(jù)對(duì)象 (Remote Data Object ,簡(jiǎn)稱RDO) 是位于 ODBC API 之上的一個(gè)對(duì)象模型薄層,它依賴 ODBC API、選定的 ODBC 驅(qū)動(dòng)程序以及后端數(shù)據(jù)庫(kù)引擎實(shí)現(xiàn)大部分的智能和功能,因此短。ù蠹s 250 K)、快速、強(qiáng)健。 RDO具備基本的 ODBC 處理方法,所以可以直接執(zhí)行大多數(shù) ODBC API 函數(shù)。RDO包含在VB4.0/VB5.0企業(yè)版中,由一個(gè)動(dòng)態(tài)連接庫(kù)MS RDO32.DLL實(shí)現(xiàn)。 當(dāng)VB版本還只是2.0時(shí),從VB訪問(wèn)MS SQL Server的手段只有API函數(shù)集(VBSQL/DBLib或 ODBC API)。VB發(fā)展到3.0時(shí),其DAO/Jet (Microsoft Access的數(shù)據(jù)庫(kù)引擎)功能非凡,具備面向?qū)ο蟮某绦蚪涌,但處理速度尚不盡如人意。另一方面,盡管VBSQL/DBLib、ODBC AP I在速度方面性能很好,但它需要花費(fèi)很大的精力進(jìn)行繁瑣的編程工作。 當(dāng)MS SQL Server發(fā)展到6.0、VB發(fā)展到4.0時(shí),開(kāi)發(fā)了新的對(duì)象模塊,由此產(chǎn)生了RDO,可以訪問(wèn)SQL Server、Oracle;RDO2.0則是由VB5.0提供的。值得一提的是,它實(shí)現(xiàn)了“事件驅(qū)動(dòng)型數(shù)據(jù)庫(kù)訪問(wèn)的編程方式”。 要討論RDO,就必然要談到DAO。DAO/Jet是為了實(shí)現(xiàn)從VB訪問(wèn)Access數(shù)據(jù)庫(kù)而開(kāi)發(fā)的程序接口(對(duì)象)。RDO是從DAO派生出來(lái)的,但兩者很大的不同在于其數(shù)據(jù)庫(kù)模式。DAO是針對(duì)[記錄(Records)]和[字段(Fields)],而RDO是作為[行(Rows)]和[列(Columns)]來(lái)處理。也就是說(shuō)DAO 是ISAM模式,RDO是關(guān)系模式。此外DAO是訪問(wèn)Access的Jet引擎(Jet是ISAM)的接口,而RDO則是訪問(wèn)ODBC的接口。 可見(jiàn),RDO是綜合了DAO/Jet、VBSQL/DBLib以及ODBC的優(yōu)點(diǎn)的對(duì)象(Object)。需要強(qiáng)調(diào)的是,RDO是包裹著ODBC API的一層薄薄的外殼,被設(shè)計(jì)成在后臺(tái)(服務(wù)器端)有數(shù)據(jù)庫(kù)存在的前提下運(yùn)行,同時(shí)也是針對(duì)SQL Server和Oracle而特別設(shè)計(jì)的。 RDO的優(yōu)勢(shì)在于它完全被集成在VB之中。此外,直接訪問(wèn)SQL Server存儲(chǔ)過(guò)程、完全支持T-SQL、T-SQL調(diào)試集成在開(kāi)發(fā)環(huán)境中、Visual Database Tools的集成化等,也是RDO的長(zhǎng)處。
RDO之后是ADO
Microsoft公司已經(jīng)明確宣布今后不會(huì)對(duì)VBSQL/DBLib進(jìn)行升級(jí),而ODBC API函數(shù)一級(jí)的編程方式也不為人們所喜愛(ài)。RDO自身今后將被以ActiveX技術(shù)為基礎(chǔ)的ADO(ActiveX Data O bjects)所替代。Visual Basic下一個(gè)版本中由哪一個(gè)作為標(biāo)準(zhǔn)配置還不很明確,但這一發(fā)展趨勢(shì)已經(jīng)很清楚。 為什么需要ADO呢?RDO是以O(shè)DBC為基礎(chǔ),而ADO則是基于全新的OLE DB技術(shù)。ODBC本身是以SQL Server、Oracle等關(guān)系數(shù)據(jù)庫(kù)作為訪問(wèn)對(duì)象;OLE DB則不僅限于此,而將是可以對(duì)電子郵件、文本文件、復(fù)合文件、數(shù)據(jù)表等各種各樣的數(shù)據(jù)通過(guò)統(tǒng)一的接口進(jìn)行存取的技術(shù)。DAO、RDO當(dāng)然不會(huì)一下子消失,但隨著新技術(shù)的利用,它們的作用將逐步淡化。
RDO的對(duì)象模塊圖
要正確地使用RDO,有必要對(duì)其對(duì)象模塊結(jié)構(gòu)加以理解。在RDO的對(duì)象和集合中,有很多對(duì)數(shù)據(jù)庫(kù)的狀態(tài)和設(shè)定進(jìn)行操作的屬性(Property),以及對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作的方法(Method)。利用這些,從RDO2.0起就可以開(kāi)發(fā)事件驅(qū)動(dòng)的數(shù)據(jù)庫(kù)應(yīng)用程序。 RDO對(duì)象與VB中其他對(duì)象的概念相同。與VB用的ActiveX控件(以往稱為Custom Control 或OCX、VBX)相似的是,RDO也帶有屬性和方法;但同Spread、InputMan等普遍應(yīng)用的Activ eX控件不同的是,RDO沒(méi)有自己的用戶界面,因而可以和VB標(biāo)準(zhǔn)的Timer控件歸為同一類。當(dāng)然也可以將RDO看作調(diào)用ODBC API函數(shù),進(jìn)而對(duì)后臺(tái)數(shù)據(jù)庫(kù)操作加以控制的對(duì)象。在RDO的屬性和方法中,包含了對(duì)單個(gè)的ODBC API函數(shù)以及一連串API函數(shù)的調(diào)用。
1. rdoEngine對(duì)象 最初調(diào)用RDO對(duì)象以及RDC(遠(yuǎn)程數(shù)據(jù)控件)時(shí),自動(dòng)生成rdoEngine對(duì)象的附帶事件(i ncident)。rdoEngine用于對(duì)RDO全局屬性的參數(shù)、選項(xiàng)進(jìn)行設(shè)置,是在RDO的階層結(jié)構(gòu)內(nèi)處于最上層的對(duì)象,包含了所有的其他對(duì)象。 rdoEngine對(duì)象與DAO/Jet不同,雖然被多個(gè)應(yīng)用程序共享,但體現(xiàn)rdoEngine對(duì)象的設(shè)定值的屬性卻并不共用,而是在各自的應(yīng)用程序的程序界面中對(duì)其分別加以設(shè)定。這些設(shè)定值對(duì)其他使用RDO以及RDC的應(yīng)用程序沒(méi)有任何影響。rdoEngine不是集合的要素,而是重新定義的對(duì)象,rdoEngine對(duì)象不能被追加作成。
2. rdoEnvironment對(duì)象 RDO對(duì)象在自動(dòng)創(chuàng)建rdoEngine對(duì)象時(shí),將rdoEnviroment對(duì)象的初始值生成并保存為rdo Enviroments(0)。一般情況下,應(yīng)用程序中不必追加rdoEnvironment對(duì)象,大多只需對(duì)已有的rdoEnviroments(0)進(jìn)行操作就可以了。只有在支持一個(gè)以上事務(wù)(Transaction),需要將用戶名和口令信息分別處理的情況下,利用rdoCreateEnvironment方法將特定的用戶名和口令值作成新的rdoEnvironment對(duì)象。在這個(gè)方法中可以指定固有名、用戶名和口令,如果所指定的值與rdoEnvironments集合的已經(jīng)存在的成員名稱相同,會(huì)產(chǎn)生錯(cuò)誤。新建的rdoEnvi ronment對(duì)象自動(dòng)追加在rdoEnvironments集合的最后。調(diào)用rdoCreateEnvironment方法時(shí),其name參數(shù)可以是長(zhǎng)度為0的文字列,這時(shí)新的rdoEnvironment對(duì)象將不會(huì)被追加在rdoEnvi ronments集合之中。
3.rdoConnection對(duì)象 rdoConnection對(duì)象用于同SQL Server的連接管理,下面是與SQL Server連接的例子。 第一步用New關(guān)鍵字聲明一個(gè)rdoConnection對(duì)象: Dim Cn as New rdoConnection 由此生成獨(dú)立的連接對(duì)象,這時(shí)它還不是rdoConnection集合的成員。在具體連接到SQL Server等之前,有必要設(shè)定rdoConnection集合的屬性。對(duì)此,使用With關(guān)鍵字編程效率會(huì)更好。
With CN
.Connect = “Uid = ; Pwd = ; Database = Pubs; DSN = MyPubsDSN; ”
'設(shè)定Cursor類型
.CursorDriver = rdUseNone
'設(shè)定登錄超時(shí)
.LoginTimeOut = 10
End With
用RDO與SQL Server連接和斷開(kāi)
RDO接口沒(méi)有自動(dòng)管理同SQL Server的連接和斷開(kāi)的功能,需由程序員自己加以判斷。這里需要注意的是對(duì)連接和斷開(kāi)時(shí)機(jī)的管理,因?yàn)橥瑫r(shí)有過(guò)多的連接將會(huì)造成服務(wù)器負(fù)載過(guò)重。而且,對(duì)SQL Server而言,一個(gè)連接只能同時(shí)支持一個(gè)操作,當(dāng)同時(shí)進(jìn)行記錄的讀出和更新時(shí),需要分別對(duì)其各自的連接加以確認(rèn)。在一定條件下需要保持連接;反之,當(dāng)操作完成以后,又需要立即將連接斷開(kāi)。如果能正確地設(shè)計(jì)好連接和斷開(kāi)的時(shí)刻,就有可能確保擴(kuò)展更多的用戶數(shù)(客戶/服務(wù)器開(kāi)發(fā)環(huán)境中,與數(shù)據(jù)庫(kù)項(xiàng)的可擴(kuò)展性一樣,客戶數(shù)擴(kuò)張的可能性也非常重要)。 由于RDO是基于ODBC,它通過(guò)ODBC的數(shù)據(jù)源名(DSN: Data Source Name)與SQL Server相連。DSN的信息可以基于文件,也可以在連接時(shí)通過(guò)傳遞的參數(shù)指定。不過(guò),一般來(lái)說(shuō),不推薦基于文件的DSN,因?yàn)橐坏〥SN文件被破壞,或者被誤刪除,設(shè)定起來(lái)就非常麻煩。通過(guò) DSN對(duì)SQL Server的連接方式一般有以下幾種:
查詢ODBC的登錄信息中是否存在有效的DSN:可以通過(guò)ODBC API的SQLDataSources函數(shù)取得DSN條目的列表,不過(guò)這種辦法實(shí)用性不大。
用rdoRegisterDataSource函數(shù)生成新的DSN:雖然多少有一些麻煩,但比查詢ODBC 登錄信息要好一些。
與已有的DSN相連:需要手工設(shè)置DSN,而且安裝應(yīng)用程序之后還需個(gè)別地設(shè)定DSN,對(duì)用戶來(lái)說(shuō)不是很友好的解決方法。
從應(yīng)用程序中自動(dòng)啟動(dòng)控制面板的ODBC管理applet,向用戶說(shuō)明DSN的設(shè)定方法:有的應(yīng)用程序就是用這種方法進(jìn)行設(shè)定,但仍不是很實(shí)用的辦法。
將SQL Server名保存在Windows Registry或INI文件,在連接時(shí)對(duì)rdoConnectio ns對(duì)象的屬性作如下設(shè)置:在初次運(yùn)行應(yīng)用程序,或者找不到指定的SQL Server名的情況下,要求用戶進(jìn)行輸入,并設(shè)置在Windows Registry或INI文件中。通常,SQL Server名不會(huì)改變;當(dāng)連接出現(xiàn)錯(cuò)誤時(shí),可以像初次運(yùn)行應(yīng)用程序時(shí)那樣,為用戶提供指定SQL Server 名的對(duì)話框,這種做法最為理想。
利用ODBC3.0驅(qū)動(dòng)支持的功能在連接時(shí)實(shí)際指定DSN文件:作安裝程序時(shí)包含這個(gè)DS N信息的文件,隨同程序一起安裝。
此外還有其他一些DSN的連接方法,這里不作一一描述。 這些方法中具體哪一個(gè)最實(shí)用,需根據(jù)各種應(yīng)用程序的安全性要求、安裝方法等進(jìn)行考慮加以選擇,一般是組合上述方法的其中幾種來(lái)編程。也就是說(shuō),用DSN文件的方式來(lái)作實(shí)際上的連接,而同時(shí)采用對(duì)DSN文件是否存在進(jìn)行檢查、不存在時(shí)要求用戶輸入SQLServer 名、用戶名、口令并即時(shí)自動(dòng)生成的方法。 實(shí)際的連接除了RDO 1.0的OpenConnection方法以外,也可以用RDO 2.0中新增加的Esta blishConnection方法,我們將在下期中介紹這些方法。此外,下面我們還將通過(guò)實(shí)際代碼向大家繼續(xù)介紹經(jīng)DSN對(duì)SQL Server的連接方式、數(shù)據(jù)的讀取、追加、更新、刪除等內(nèi)容。
實(shí)例
在本系列文章的上篇刊文中,我們介紹了RDO的發(fā)展、優(yōu)勢(shì)、對(duì)象模塊、趨勢(shì),以及通過(guò)RDO與SQL Server的連接和斷開(kāi)等內(nèi)容,本期將通過(guò)實(shí)例來(lái)介紹RDO的應(yīng)用。
OpenConnection方法的調(diào)用方式如下:
[調(diào)用方式:OpenConnection(dsName, Prompt, ReadOnly, Connect)]
其中參數(shù)說(shuō)明如下:
dsName,指定登錄在系統(tǒng)中的DSN條目。當(dāng)用Connect參數(shù)指定DSN值時(shí),dsName必須為“”(長(zhǎng)度為0的文字列)。
Prompt,當(dāng)設(shè)置為rdDriverPrompt常數(shù)時(shí),可以在不能與SQL Server連接的情況下,激活ODBC設(shè)置對(duì)話框來(lái)設(shè)定DSN。只是最好不要讓一般用戶隨意更改這個(gè)設(shè)定。通常情況下,正確的處理方法是設(shè)定為rdDriverNoPrompt,利用Error處理程序編程進(jìn)行處理。
ReadOnly,若需要通過(guò)連接對(duì)數(shù)據(jù)進(jìn)行更新時(shí)設(shè)定為False。若沒(méi)有數(shù)據(jù)更新的必要?jiǎng)t設(shè)為True,這時(shí)因?yàn)镺DBC驅(qū)動(dòng)沒(méi)有對(duì)數(shù)據(jù)更新進(jìn)行管理的需要,可以提高程序效率。
Connect,向ODBC驅(qū)動(dòng)管理器傳遞所有的ODBC連接參數(shù)?梢允÷詃sName,只通過(guò)Co nnect參數(shù)進(jìn)行包括用戶名、口令、缺省數(shù)據(jù)庫(kù)、DSN(此時(shí)dsName參數(shù)的值無(wú)效)等全部參數(shù)值的傳遞。
下面是OpenConnection方法的一個(gè)實(shí)例。
設(shè)定的DSN為MyDSN:
Dim Cn As rdoConnection
Dim En As rdoEnvironment
Dim Conn As String
Conn = “DSN = MyDSN; UID = Jacob;” & “PWD = 123456; DATABASE = MyDb;”
Set Cn = En.OpenConnection(“”, rdDriverPrompt, False, Conn)
在這個(gè)例子中,dsName是空 “”(長(zhǎng)度為0的文字列)。DSN情報(bào)從Conn參數(shù)中所含的DSN = MyDSN取得。
OpenConnection方法中也可以通過(guò)變量來(lái)進(jìn)行參數(shù)傳遞:
[變量名:=值]
Set Cn = En.OpenConnection(Prompt := rdDriverPrompt, ReadOnly := False, Conn ect := Cnn)
雖然這多少有一些多余的代碼,但毫無(wú)疑問(wèn)會(huì)使程序維護(hù)工作容易得多。
EstablishConnection方法
EstablishConnection方法的調(diào)用方式如下:
調(diào)用方式:EstablishConnection(Prompt, ReadOnly, Connect)
本文前面對(duì)獨(dú)立(stand alone)的連接對(duì)象(rdoConnection)作了說(shuō)明,EstablishCon nection方法可以用于這種情況。EstablishConnection方法同OpenConnection方法很相似,被用于停止?fàn)顟B(tài)或獨(dú)立的rdoConnection對(duì)象。
這里以獨(dú)立的rdoConnection對(duì)象為例說(shuō)明與SQL Server的連接。
Public WithEvents Eng As rdoEngine
Public WithEvents Cn As rdoConnection
Private Sub Form_Load()
Set Eng = New rdoEngine
Set Cn = New rdoConnection
With Cn
.Connect = “UID = ; PWD = ;” & “DATABASE = pubs; DSN = biblio”
.LoginTimeout = 5
.EstablishConnection rdoDriverNoPromt, True, rdAsyncEnable
End With
End Sub
在這個(gè)例子中,F(xiàn)orm_Load函數(shù)對(duì)rdoEngine和rdoConnection對(duì)象進(jìn)行初始化。這里有一點(diǎn)需要注意,rdoConnection對(duì)象是處于獨(dú)立的狀態(tài)之下,即使是處于未連接狀態(tài)也可以設(shè)置屬性的值。
接下來(lái)是rdoConnect對(duì)象的事件處理程序。從RDO 2.0起可以實(shí)現(xiàn)異步方式(rdAsyncEn able),EstablishConnection就設(shè)定為該值。在異步狀態(tài)下,不必等待與數(shù)據(jù)庫(kù)的連接,程序可以迅速?gòu)腇orm_Load函數(shù)中退出。
然后是BeforeConnect事件,該處理在與數(shù)據(jù)庫(kù)的連接開(kāi)始以前被激發(fā),此時(shí)不能進(jìn)行有關(guān)終止連接的操作:
Private Sub Cn_BeforeConnect(ConnetString As String, Prompt As Variant)
MsgBox “正在連接” & ConnectString, vbOKOnly, “連接前”
End Sub
連接完成之后的事件處理:
Private Sub Cn_Connect(ByVal ErrorOccurred As Boolean)
Dim M As String
If ErrorOccurred Then
For Each er In rdoErrors
M = M & er & vbCrLf & M
Next
MsgBox “連接失敗” & vbCrLf & M
Else
MsgBox “連接成功”
'這是確認(rèn)連接狀態(tài)的測(cè)試代碼
Cn.Excute “use pubs”
End If
End Sub
RDO連接處理結(jié)束后,在該事件中確認(rèn)連接成功與否。連接成功的情況下ErrorOccurred 返回False,失敗時(shí)為True,由此可以對(duì)rdoErrors集合進(jìn)行檢測(cè):
Private Sub Eng_InfoMessage()
For Each er In rdoErrors
Debug.Print er
Next
RdoErrors.Clear
End Sub
不能與SQL Server連接的原因多種多樣,有可能是由于對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)權(quán)限、網(wǎng)絡(luò)連接問(wèn)題、數(shù)據(jù)庫(kù)表的信息錯(cuò)誤、SQL Server同時(shí)連接的許可數(shù)、資源不足等等,具體情況需要與網(wǎng)絡(luò)管理員商量。
斷開(kāi)連接的操作非常簡(jiǎn)單,但又很重要,因?yàn)镽DO不提供自動(dòng)斷開(kāi)的功能。
Cn.Close
Set Cn = Nothing '釋放對(duì)象所占的內(nèi)存資源
En.Close
Set En = Nothing '釋放對(duì)象所占的內(nèi)存資源
VB是對(duì)象語(yǔ)言,F(xiàn)orm、ActiveX控件也都是對(duì)象。使用對(duì)象后必須養(yǎng)成將對(duì)象設(shè)為Nothi ng把它從內(nèi)存中釋放的編程習(xí)慣。這樣可以預(yù)防很多不可預(yù)測(cè)錯(cuò)誤,往往程序中發(fā)生意義不明的錯(cuò)誤時(shí),其原因就在于此。
數(shù)據(jù)的取得
與數(shù)據(jù)庫(kù)連接成功之后,接下來(lái)就是取得數(shù)據(jù)。一般用OpenResultset方法取得數(shù)據(jù),這里首先需理解數(shù)據(jù)庫(kù)中與此有關(guān)的[游標(biāo)]概念。
一言以蔽之,游標(biāo)[cursor]就是指向依據(jù)一定的條件從數(shù)據(jù)庫(kù)中抽取的數(shù)據(jù)的多個(gè)指針。也就是說(shuō)游標(biāo)是用作指向由數(shù)據(jù)庫(kù)返回的數(shù)據(jù)的方法。
RDO 支持幾種不同的游標(biāo)庫(kù),其中每一種都有其特定的作用:向前滾動(dòng)型的結(jié)果集(rdOpenForwardOnly-缺省值)、靜態(tài)滾動(dòng)型結(jié)果集(rdOpenStatic)、可滾動(dòng)的查詢結(jié)果集(rdOpenKeyset)和動(dòng)態(tài)可滾動(dòng)的查詢結(jié)果集(rdoOpenDynamic)。在使用RDC的情況下,游標(biāo)的值設(shè)定為ResultsetType屬性;在使用RDO的情況下,通過(guò)OpenResultset方法的Type參數(shù)進(jìn)行設(shè)定。游標(biāo)又分為[服務(wù)器端游標(biāo)]和[客戶端游標(biāo)],這需要根據(jù)程序的性質(zhì)、處理內(nèi)容的不同來(lái)選擇適當(dāng)?shù)姆绞。也有不使用游?biāo)的情況,比如當(dāng)只進(jìn)行數(shù)據(jù)讀取時(shí),使用rdUseNone選項(xiàng)更為合適。
關(guān)于是否使用游標(biāo)、使用何種游標(biāo),需考慮下面一些情況:
* 需要讀取多少行數(shù)據(jù)?要讀取全部或只是幾行數(shù)據(jù)?
* 是否等待游標(biāo)的創(chuàng)建完成?對(duì)于用戶來(lái)說(shuō)等待時(shí)間是否在允許范圍之內(nèi)?
* 用來(lái)保存已創(chuàng)建游標(biāo)的系統(tǒng)資源(內(nèi)存容量),在用戶端或服務(wù)器端是否充足?
* 從服務(wù)器端返回的結(jié)果怎樣讀。坑斜匾獜漠(dāng)前行隨意移動(dòng),還是從最初到最后順序讀取為好?
* 游標(biāo)的成員關(guān)系怎樣定義?
* 數(shù)據(jù)如何更新?數(shù)據(jù)有沒(méi)有更新的必要?是通過(guò)Execute方法將游標(biāo)的數(shù)據(jù)進(jìn)行更新,或是由存儲(chǔ)過(guò)程更新?
關(guān)于游標(biāo)的詳細(xì)介紹,請(qǐng)參照Visual Basic Books Online以及SQL Server用戶手冊(cè)。這里介紹從RDO對(duì)象讀取數(shù)據(jù)的幾種方法:
* rdoResultset對(duì)象,這是RDO的基本游標(biāo)對(duì)象。與DAO的Recordset對(duì)象相似,可應(yīng)用于各種游標(biāo)以及無(wú)游標(biāo)的場(chǎng)合?梢酝ㄟ^(guò)rdoConnect對(duì)象或rdoQuery對(duì)象的OpenResultset方法創(chuàng)建rdoResultset對(duì)象。
* rdoQuery對(duì)象,與DAO的QueryDef相似,在進(jìn)行一次性查詢時(shí)使用,用于取代已經(jīng)過(guò)時(shí)的由rdoConnection對(duì)象的CreatePreparedStatement方法創(chuàng)建的rdoPreparedStatement對(duì)象。rdoQuery對(duì)象直接調(diào)用ODBC的SQLPrepare。
* UserConnection對(duì)象,在VB5.0以及RDO 2.0中新增加的對(duì)象,這里不作詳細(xì)闡述。它是一個(gè)非常優(yōu)秀的對(duì)象,使RDO使用起來(lái)更加容易。
* rdoTable對(duì)象,是rdoTables集合的成員,用來(lái)顯示SQL Sever上的一個(gè)表的內(nèi)容。
編程中通常運(yùn)用前3種方法中的某一種,而第4種一般不太用。
不論使用哪一種方法,都有必要給出SQL語(yǔ)句。在絕大多數(shù)的情況下,SQL語(yǔ)句是針對(duì)SQL Server,從哪個(gè)表以何種條件讀取哪一行的數(shù)據(jù),如(SELECT * FROM table1 WHERE field1 = “condition”)。運(yùn)行存儲(chǔ)過(guò)程時(shí)用Name參數(shù)指定存儲(chǔ)過(guò)程,程序能自動(dòng)判別是RDO 2.0的還是存儲(chǔ)過(guò)程的SQL語(yǔ)句。在以存儲(chǔ)過(guò)程為核心的情況下,利用UserConnection將存儲(chǔ)過(guò)程作為方法來(lái)處理最為妥當(dāng)。
下面給出一個(gè)運(yùn)行rdoConnection對(duì)象Cn的OpenResultset方法的例子。
Dim Rs As Resultset
Set Rs = Cn.OpenResultset(name:=“SELECT * FROM Authors WHERE Year_Born=1966”)
If Rs.RowCount > 0 Then
MsgBox Rs.RowCount & “條記錄取得完畢!
Else
MsgBox “沒(méi)有取得任何記錄!
End If
這個(gè)例子中用了name:=,OpenResultset方法,除了name參數(shù)以外,也可以使用lock、 locktype、option等。下面是從Resultset中將數(shù)據(jù)讀取到ListBox中的方法:
Do Until Rs.EOF
List1.AddItem Rs(“au_lname”)
Rs.MoveNext
Loop
存儲(chǔ)過(guò)程雖然不在本文討論的范圍內(nèi),這里也簡(jiǎn)單地介紹一下。存儲(chǔ)過(guò)程基本上有以下4種類型:
{call myStoreProcedure} ' 沒(méi)有參數(shù)的存儲(chǔ)過(guò)程
{call myStoreProcedure(?)} ' 單一的輸入或輸出參數(shù)
{? = call myStoreProcedure(?)} ' 單一參數(shù)、有返回值
{? = call myStoreProcedure(?, ?)} ' 多個(gè)參數(shù)、有返回值
下面演示一個(gè)運(yùn)行存儲(chǔ)過(guò)程的例子:
sp_GetVendorCount參數(shù)是名稱的條件,其返回值為符合該條件的記錄數(shù)。
Dim CPw As rdoQuery
Dim sSQL As String
SSQl = “{? = call sp_GetVendorCount(?)}”
這里“名稱的條件”是輸入?yún)?shù),由ODBC驅(qū)動(dòng)器進(jìn)行自動(dòng)識(shí)別。使用rdoParameters(n).Direction可以對(duì)返回值(rdParamReturnValue)、輸入?yún)?shù) (rdParamInput) 、輸出參數(shù)(rdParamOutput)和輸入輸出參數(shù)(rdParamInputOutput)加以控制。但通常ODBC都會(huì)讀入存儲(chǔ)過(guò)程的定義式,并加以正確識(shí)別,所以絕大多數(shù)的情況下不必使用這個(gè)參數(shù)。
Dim CPw = Cn.CreateQuery(“GetVendorCount”, sSQL)
代碼生成名為GetVendorCount的rdoQuery對(duì)象,并將rdoQuery對(duì)象自動(dòng)增加到rdoQueries集合中,以后可以重復(fù)使用。
現(xiàn)在將CPw對(duì)象的第一個(gè)參數(shù)指定為返回值:
CPw.rdoParameters(0).Direction = rdParamReturnValue
最后由Execute方法運(yùn)行:
CPw.Execute
返回行的查詢(存儲(chǔ)過(guò)程中包含一個(gè)以上的SELECT)時(shí),可使用OpenResultset方法。運(yùn)行后,可通過(guò)rdoParameters集合取得返回值:
If CPw.rdoParameters(0) > 0 Then
MsgBox CPw.rdoParameters & “數(shù)據(jù)取得成功”
Else
MsgBox “數(shù)據(jù)讀取失敗”
End If
數(shù)據(jù)的追加、更新、刪除
對(duì)SQL語(yǔ)句已經(jīng)有一定了解的讀者,應(yīng)該比較熟悉INSERT、UPDATE、DELETE等語(yǔ)句。對(duì)于rdoConnection對(duì)象,雖然可以在OpenResultset的Name參數(shù)中直接代入SQL語(yǔ)句,用Execute方法運(yùn)行,但沒(méi)有充分利用RDO對(duì)象的長(zhǎng)處。在rdoResultset中有AddNew、Edit、Update、Delete、MoveNext、MovePrevious、MoveFirst、MoveLast方法,與DAO/Jet相似,用起來(lái)非常便利。
下面在先前的Resultset的例子中追加記錄:
Rs.AddNew
Rs(“au_id”) = “111-46-1992”
Rs(“au_lname”) = “Takenami”
RS(“au_fname”) = “Teruo”
'設(shè)定所有的field,通常調(diào)用Call SetField,在別的模塊中設(shè)定
Rs.Update
與SQL語(yǔ)句中的INSERT相比起來(lái),這種方法非常簡(jiǎn)單,而且代碼可讀性好。記錄的更新方法如下,與追加相似,所不同的只有最初的Edit方法:
Rs.Edit
Rs(“au_lname”) = “Takenami”
RS(“au_fname”) = “Teruo”
'設(shè)定所有的field,通常調(diào)用Call SetField,在別的模塊中設(shè)定
Rs.Update
在實(shí)際應(yīng)用中,字段的更新放在別的模塊中,便于從AddNew、Edit兩種處理中都可以進(jìn)行調(diào)用。
使用Delete方法刪除記錄時(shí),當(dāng)前行被刪除。當(dāng)前行可以通過(guò)MoveNext、MovePrevious等Move方法以及Bookmark屬性設(shè)定。
Rs.Delete '刪除當(dāng)前記錄
這里需要注意的是當(dāng)前記錄被刪除之后記錄指針的位置。Delete執(zhí)行后,記錄指針仍然指向已被刪除的記錄,也就是空的記錄,對(duì)這個(gè)空記錄進(jìn)行讀寫操作會(huì)產(chǎn)生錯(cuò)誤。所以通常在Delete之后應(yīng)立即執(zhí)行ReQuery或MoveNext操作:
Rs.ReQuery 或 Rs.MoveNext
以上簡(jiǎn)單地說(shuō)明了數(shù)據(jù)的增加、更新、刪除方法,根據(jù)數(shù)據(jù)庫(kù)的模式的不同,增加、更新會(huì)變得非常復(fù)雜。另外,由于數(shù)據(jù)表的原因,有時(shí)會(huì)使得刪除操作變得復(fù)雜。通常與數(shù)據(jù)表的構(gòu)造、相關(guān)性有關(guān)的處理,為了使客戶端的代碼盡可能簡(jiǎn)潔,應(yīng)在SQL Server上創(chuàng)建觸發(fā)器。有關(guān)觸發(fā)器的內(nèi)容已超出了本文討論的范圍,這里不詳細(xì)說(shuō)明。本文介紹的只是一些基本的操作方法,RDO數(shù)據(jù)處理功能不僅限于此,讀者可在實(shí)際開(kāi)發(fā)中進(jìn)一步領(lǐng)會(huì)。
總結(jié)
RDO是開(kāi)發(fā)數(shù)據(jù)庫(kù)應(yīng)用程序功能強(qiáng)大的對(duì)象方法,要真正做到應(yīng)用自如,需要付出很大努力。本文描繪了RDO基本的構(gòu)成、功能、編程方式,希望讀者由此對(duì)數(shù)據(jù)庫(kù)編程方式以及RDO的使用有更為充分的了解。如果需要進(jìn)一步研究,建議可以從以下幾方面入手:
* SQL Server(或Oracle)的功能,特別是存儲(chǔ)過(guò)程、View、觸發(fā)器、安全模式等;
* 數(shù)據(jù)庫(kù)設(shè)計(jì)基礎(chǔ);
* SQL語(yǔ)句;
* Visual Basic的對(duì)象概念。
這些粗看起來(lái)與RDO沒(méi)有什么聯(lián)系,但實(shí)際上有助于對(duì)RDO的結(jié)構(gòu)、原理等基本技術(shù)的理解。換而言之,學(xué)習(xí)數(shù)據(jù)庫(kù)編程的基本內(nèi)容為大前提,RDO或者ADO的應(yīng)用不過(guò)是訪問(wèn)數(shù)據(jù)庫(kù)的一種手段而已。