在VB中兼容非ACCESS數(shù)據(jù)庫的技巧
發(fā)表時間:2024-02-21 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]本文從VB數(shù)據(jù)庫體系結(jié)構(gòu)的角度出發(fā),結(jié)合一個具體實例,闡述了在VB中兼容非ACCESS格式數(shù)據(jù)庫的具體方法和技巧。 關(guān)鍵詞:VB、非ACCESS數(shù)據(jù)庫、數(shù)據(jù)存取對象 一個完整的數(shù)據(jù)庫管理系統(tǒng)(DBMS)應(yīng)是能兼容市面上各種較流行數(shù)據(jù)格式的系統(tǒng),它充分考慮了不同用戶的實際要求。鑒于目前市面上...
本文從VB數(shù)據(jù)庫體系結(jié)構(gòu)的角度出發(fā),結(jié)合一個具體實例,闡述了在VB中兼容非ACCESS格式數(shù)據(jù)庫的具體方法和技巧。
關(guān)鍵詞:VB、非ACCESS數(shù)據(jù)庫、數(shù)據(jù)存取對象
一個完整的數(shù)據(jù)庫管理系統(tǒng)(DBMS)應(yīng)是能兼容市面上各種較流行數(shù)據(jù)格式的系統(tǒng),它充分考慮了不同用戶的實際要求。鑒于目前市面上有多種數(shù)據(jù)庫格式(如Foxpro、DBase、Paradox等)流行,因而在VB數(shù)據(jù)庫應(yīng)用程序中兼容非Access數(shù)據(jù)庫就顯得尤為重要了。
作為一種流行的開發(fā)平臺,VB提供了強大的數(shù)據(jù)庫功能。主要有以下三種:數(shù)據(jù)控件法:使用數(shù)據(jù)存取對象(Data Access Object )法;直接調(diào)用ODBC 2.0 API接口函數(shù)法。其中調(diào)用數(shù)據(jù)存取對象的方法相對其它兩種方法具有方便靈活、功能強大的突出優(yōu)點。本文即從調(diào)用數(shù)據(jù)庫存取對象的方法出發(fā),實現(xiàn)了非Access格式數(shù)據(jù)庫(以FoxPro數(shù)據(jù)庫為例)的建新庫、拷貝數(shù)據(jù)庫結(jié)構(gòu)、動態(tài)調(diào)入等操作,闡述了從編程技巧上彌補VB對這些外來數(shù)據(jù)庫支持不足的可行性。
一、VB數(shù)據(jù)庫的體系結(jié)構(gòu)
VB數(shù)據(jù)庫的核心結(jié)構(gòu)是所謂的MicroSoft JET數(shù)據(jù)庫引擎,它為VB與數(shù)據(jù)庫的接口提供了基本的方法和手段。JET引擎被Visual Basic、Microsoft Access和其它Microsoft產(chǎn)品所共享。因而在VB中Access數(shù)據(jù)庫格式是一種標準的內(nèi)置格式,所有的非Access數(shù)據(jù)庫都被稱為外來數(shù)據(jù)庫。
JET引擎的作用就像是一塊“面板”,在其上可以插入多種索引順序存取方法(即ISAM)數(shù)據(jù)驅(qū)動程序。這就是VB對非Access數(shù)據(jù)庫具有豐富支持的真正原因。VB專業(yè)版中提供了FoxPro、dBASE(或Xbase)、Paradox、Btrieve等數(shù)據(jù)庫的ISAM驅(qū)動程序,這就使得VB能支持這些數(shù)據(jù)庫格式。另外,其他的許多兼容ISAM的驅(qū)動程序也可以通過從廠商的售后服務(wù)得到。因而從理論上說,VB能支持所有兼容ISAM的數(shù)據(jù)庫格式(前提是只需獲得這些數(shù)據(jù)庫的ISAM驅(qū)動接口程序)。
二、使用非Access數(shù)據(jù)庫時的參數(shù)設(shè)置及配置文件的參數(shù)讀取
值得注意的是,大多數(shù)的程序員都不注重數(shù)據(jù)庫配置文件的使用,殊不知這是極為重要的。
如果在VB的程序中使用了數(shù)據(jù)庫的操作,將應(yīng)用程序生成EXE文件或打包生成安裝程序后,則必須提供一個數(shù)據(jù)庫配置(.INI)文件,在INI文件中可以對不同類型的數(shù)據(jù)庫進行設(shè)置。如果找不到這個INI文件,將會導(dǎo)致不能訪問數(shù)據(jù)庫。通常情況下,INI文件的文件名和應(yīng)用程序的名稱相同,所以如果沒有指明,VB的程序會在Windows子目錄中去找和應(yīng)用程序同名的INI文件?梢允褂肰B中的SetDataAccessOptions語句來設(shè)置INI文件。
SetDataAccessOptions語句的用法如下:
SetDataAccessOptions 1,IniFileName
其中IniFileName參數(shù)指明的是INI文件的帶路徑的文件名。
值得注意的是,當(dāng)應(yīng)用程序找不到這個INI文件時,或在調(diào)用OpenDataBase函數(shù)時對其Connect參數(shù)值沒有設(shè)定為VB規(guī)定的標準值,如對FoxPro 2.5格式設(shè)定為了“FoxPro;”(應(yīng)為“FoxPro 2.5;”),或者沒有安裝相應(yīng)的ISAM驅(qū)動程序,則此時VB會顯示一條錯誤信息“Not Found Installable ISAM”。
通常,INI文件在應(yīng)用程序分發(fā)出去以前已經(jīng)生成,或者在安裝時動態(tài)生成,也可以在應(yīng)用程序中自己生成。通常這種INI文件中有“[Options]”、“[ISAM]”、“[Installed ISAMs]”、“[FoxPro ISAM]”、“[dBASE ISAM]”、“[Paradox ISAM]”等設(shè)置段,對于一個完整的應(yīng)用程序則還應(yīng)有一個屬于應(yīng)用程序自己的設(shè)置段如“[MyDB]”。可在其中設(shè)置DataType、Server、DataBase、OpenOnStartup、DisplaySQL、QueryTimeOut等較為重要的數(shù)據(jù)庫參數(shù),并以此限定應(yīng)用程序一般的運行環(huán)境。
Windows API接口函數(shù)在Win95系統(tǒng)提供的動態(tài)鏈接庫中提供了一個OSWritePrivateProfileString函數(shù),此函數(shù)能按Windows下配置文件(.INI)的書寫格式寫入信息。
在通常情況下,應(yīng)用程序還需要在運行時讀取配置文件內(nèi)相關(guān)項的參數(shù)。比如PageTimeOut(頁加鎖超時時限)、MaxBufferSize(緩沖區(qū)大小)、LockRetry(加鎖失敗時重試次數(shù))等參數(shù),通過對這些參數(shù)的讀取對應(yīng)用程序運行環(huán)境的設(shè)定、潛在錯誤的捕獲等均會有很大的改善。
設(shè)此應(yīng)用程序的數(shù)據(jù)庫配置文件為MyDB.INI,則具體過程如下:
Funtion GetINIString$( Byval Fname$,Byval szItem$,Byval szDeFault$ )
’此自定義子函數(shù)實現(xiàn)INI文件內(nèi)設(shè)置段內(nèi)參數(shù)的讀取
Dim Tmp As String, x As Integer
Tmp = String( 2048,32 )
x = OSGetPrivateProfileString( Fname$,szItem$,szDefault$,Tmp,Len(Tmp),“MyDB.INI”)
GetINIString = Mid$( Tmp,1,x )
End Function
通過此函數(shù)就能實現(xiàn)對各種數(shù)據(jù)庫格式的讀取。
三、調(diào)用數(shù)據(jù)存取對象對非Access數(shù)據(jù)庫編程的方法及其實例
VB專業(yè)版中使用數(shù)據(jù)庫存取對象變量(DAO)的方法最具有功能強大、編程靈活的特點。它能夠在程序中存取ODBC 2.0的管理函數(shù);可以控制多種記錄集類型:Dynaset,Snapshot及Table記錄集合對象;可以存儲過程和查詢動作;可以存取數(shù)據(jù)庫集合對象,例如TableDefs,F(xiàn)ields,Indexes及QueryDefs;具有真正的事物處理能力。這種方法對數(shù)據(jù)庫處理的大多數(shù)情況都非常適用。
從VB的程序代碼的角度來看,提供給VB程序員的記錄集對象(RecordSet)同所使用的數(shù)據(jù)庫格式及類型是相互獨立的。即對FoxPro等數(shù)據(jù)庫仍然可以使用眾多的數(shù)據(jù)庫存取對象變量,這就為非Access數(shù)據(jù)庫的訪問提供了最重要的前提和方法。
在VB中從一種數(shù)據(jù)庫類型轉(zhuǎn)化為另一種數(shù)據(jù)庫類型幾乎不需要或只需要很少的代碼修改。而且,盡管dBASE、Paradox本身的DDL(Data Definition Language,即數(shù)據(jù)定義語言)和DML(Data Manipulation Language,即數(shù)據(jù)操縱語言)是非結(jié)構(gòu)化查詢的,但它們?nèi)匀豢梢允褂肰B的SQL語句和JET引擎來操縱。
因而對FoxPro等非Access數(shù)據(jù)庫而言,調(diào)用數(shù)據(jù)庫存取對象的方法同樣也是一種最佳的選擇。
(一)非Access數(shù)據(jù)庫的新建及庫結(jié)構(gòu)的修改
VB專業(yè)版中的數(shù)據(jù)庫存取對象變量可以分為兩類,一類用于數(shù)據(jù)庫結(jié)構(gòu)的維護和管理,另一類用于數(shù)據(jù)的存取。其中表示數(shù)據(jù)庫結(jié)構(gòu)時可以使用下面的對象:DataBase、TableDef、Field、Index,以及三個集合(Collection):TableDefs、Fields和Indexes。每一個集合都是由若干個對象組成的,這些數(shù)據(jù)對象的集合可以完全看作是一個數(shù)組,并按數(shù)組的方法來調(diào)用。
一旦數(shù)據(jù)庫對象建立后,就可以用它對數(shù)據(jù)庫的結(jié)構(gòu)進行修改和數(shù)據(jù)處理。
對于非Access數(shù)據(jù)庫,大部分都是對應(yīng)于一個目錄,所以可以使用VB的MkDir語句先生成一個目錄,亦即新建一個數(shù)據(jù)庫。而每一個非Access數(shù)據(jù)庫文件可看作是此目錄下的一個數(shù)據(jù)表(Table),但實際上它們是互相獨立的。
下面是新建一個FoxPro 2.5格式數(shù)據(jù)庫的程序?qū)嵗?nbsp;
Sub CreateNew ( )
Dim Db1 As database, Td As TableDefs
Dim T1 As New Tabledef,F(xiàn)1 As New Field, F2 As New Field, F3 As New Field
Dim Ix1 As New Index
Dim Path As String
Const DB_TEXT = 10,DB_INTEGER = 3
ChDir "\"
Path$ = InputBox( "請輸入新路徑名:", "輸入對話框" )
MkDir Path$ ’新建一個子目錄
Set Db1 = OpenDatabase(Path$, True, False, "FoxPro 2.5;")
Set Td = Db1.TableDefs
T1.Name = "MyDB" ’新建一個數(shù)據(jù)表,數(shù)據(jù)表名為MyDB
F1.Name = "Name", F1.Type = DB_TEXT, F1.Size = 20
F2.Name = "Class", F2.Type = DB_TEXT, F2.Size = 20
F3.Name = "Grade", F3.Type = DB_INTEGER
T1.Fields.Append F1 ’向數(shù)據(jù)表中添加這些字段
T1.Fields.Append F2
T1.Fields.Append F3
Ix1.Name = "Name" ,Ix1.Fields = "Name", Ix1.Primary = True ’新建索引
T1.Indexes.Append Ix1 ’向數(shù)據(jù)庫的Indexes集合中添加新的索引
Td.Append T1 ’向TableDefs集合中添加新表
Db1.Close ’必須先關(guān)閉數(shù)據(jù)庫對象再退出
End Sub
在此段程序中值得注意的是,對非Access數(shù)據(jù)庫的新建不用CreateDatabase函數(shù),而是用OpenDatabase函數(shù),這點與Access數(shù)據(jù)庫大不一樣,但也僅僅是針對非Access數(shù)據(jù)庫而言才能用OpenDatabase函數(shù)來新建一個數(shù)據(jù)庫對象。
在VB中,外來數(shù)據(jù)庫的不同格式只在OpenDatabase函數(shù)的最后一個參數(shù)Connect中有所體現(xiàn),不同格式的外來數(shù)據(jù)庫其Connect參數(shù)值也不同,除此以外,在VB專業(yè)版中其編程的方法和步驟及技巧是基本相同的。
新建子目錄后,不能用ChDir語句進入它,否則會出現(xiàn)“‘MyDB’ is not a valid path”的錯誤。同時,對F1、F2、F3等新建字段對象的定義也必須分別定義,否則會出現(xiàn)“Element not defined”(變量未定義)的錯誤。
通過一定的編程技巧還可以實現(xiàn)非Access數(shù)據(jù)庫的庫結(jié)構(gòu)的拷貝,下面是一段相應(yīng)的程序。
Function GetPos( TFname$ ) ’此自定義函數(shù)完成對帶路徑文件名中最后一個“\”符號的定位
Dim I As Integer,Tmp As String
Tmp$ = TFname$
For I = 0 To 255
Pos% = Pos% + InStr( 1, Tmp$, "\" )
E1% = InStr( 1, Tmp$, "\" )
Tmp$ = Right$( Tmp$, Len(TFname$) - Pos% )
If E1% = 0 Then ’找到最后一個“\”符號的位置,并記下來
GetPos = Pos%
Exit For
End If
Next I
End Funtion
Sub CopyStruc( )
Dim Db1 As database, Ds1 As Dynaset,Td As TableDefs, Fld As Fields
Dim Fname,SourceF,DestF,Path As String,Pos1 As Integer
CMD1.Filter = "FoxPro數(shù)據(jù)庫文件(*.DBF) *.DBF 所有文件 *.*" ’CMD1為一個對話框的控制名
CMD1.DialogTitle = "調(diào)入Ms FoxPro數(shù)據(jù)庫文件"
CMD1.FilterIndex = 1
CMD1.Action = 1
DestF$ = InputBox$( "請輸入目標文件名:", "輸入對話框" )
If CMD1.FileName = “ ”O(jiān)r DestF$ = " " Then
MsgBox "源文件或目標文件名為空"
Exit Sub
Else
SourceF$ = CMD1.Filename
End If
FileCopy SourceF$, DestF$
Pos1% = GetPos( SourceF$ )
Path$ = Left$( SourceF$, Pos1% ) ’獲得源文件所在的路徑名
Fn$ = Left$( DestF$, InStr(1, DestF$, ".") - 1 ) ’獲得新文件的數(shù)據(jù)庫名
’Fn$為實際的Foxpro數(shù)據(jù)庫名,也即CreateDynaset函數(shù)內(nèi)的source屬性值
Set Db1 = OpenDatabase( Path$, True, False, "FoxPro 2.5;" )
Set Ds1 = Db1.CreateDynaset( Fn$ )
If Ds1.EOF And Ds1.BOF Then ’數(shù)據(jù)庫內(nèi)的無記錄則退出
TotalNum% = 0
MsgBox "此數(shù)據(jù)表為空表!"
Exit Sub
End If
’刪除記錄,保留庫結(jié)構(gòu)
Ds1.MoveFirst
Do
Ds1.Delete
Ds1.MoveNext
Loop Until Ds1.EOF
End Sub
可見,拷貝庫結(jié)構(gòu)的方法在于把一個已存在的數(shù)據(jù)庫拷貝到一個新文件中,然后再刪除新文件內(nèi)的所有記錄,保留其庫結(jié)構(gòu),得到的就是一個新建的庫結(jié)構(gòu)完整的空庫。
(二)非Access數(shù)據(jù)庫的動態(tài)調(diào)入
在實際應(yīng)用的很多情況下,經(jīng)常需要在對一些事先并不知道其具體庫結(jié)構(gòu)的數(shù)據(jù)庫進行調(diào)入、顯示及打印其記錄。因而實現(xiàn)未知格式數(shù)據(jù)庫的動態(tài)調(diào)入也是評價VB數(shù)據(jù)庫應(yīng)用程序兼容性的一個重要標志。
在VB中,網(wǎng)格控件非常適合用于瀏覽數(shù)據(jù)庫中的數(shù)據(jù),只需把數(shù)據(jù)放入網(wǎng)格即可。
在使用網(wǎng)格時動態(tài)調(diào)入的關(guān)鍵在于記錄(Colume)內(nèi)容和字段(Row)內(nèi)容(包括字段的名稱、類型、值等)的讀取,因而生成一個可以對應(yīng)于一個或多個數(shù)據(jù)表中的全部或部分記錄的Dynaset對象是非常必要的。Dynaset對象還可以是一個動態(tài)查詢的結(jié)果,能進行記錄的增加、刪除和修改等操作。
下面是一段用網(wǎng)格顯示FoxPro數(shù)據(jù)庫的程序。
Sub DBLoad( )
Dim Db1 As database, Ds1 As Dynaset,Td As TableDefs,F(xiàn)ld As Fields
Dim Fname,Tmp,Path ToTalNum As String,I,J,Pos1 As Integer
Dim MyNum ’定義一個變體型數(shù)據(jù)
CMD1.Filter = "FoxPro數(shù)據(jù)庫文件(*.DBF) *.DBF 所有文件 *.*"
CMD1.DialogTitle = "調(diào)入Ms FoxPro數(shù)據(jù)庫文件"
CMD1.FilterIndex = 1
CMD1.Action = 1
Fname$ = CMD1.Filename
Pos1% = GetPos( Fname$ )
Path$ = Left$( Fname$, Pos1% )
Tmp$ = Right$( Fname$, Len(Fname$)-Pos1)
Fn$ = Left$( Tmp$, Instr( 1,Tmp$,“.”) - 1 )
Set Db1 = OpenDatabase( Path$, True, False, "FoxPro 2.5;" )
Set Ds1 = Db1.CreateDynaset( Fn$ )
If Ds1.EOF And Ds1.BOF Then "數(shù)據(jù)庫表內(nèi)無記錄則退出
TotalNum = 0
MsgBox "此數(shù)據(jù)表為空表!"
Exit Sub
Else "顯示數(shù)據(jù)庫表內(nèi)的實際記錄數(shù)
Ds1.MoveLast
TotalNum = Ds1.RecordCount
Grid1.Rows = TotalNum + 1 ’置網(wǎng)格的實際行數(shù)
Total.Caption = Str$(TotalNum)
End If
"置網(wǎng)格的實際列數(shù)并置每列的寬度
Set Td = Db1.TableDefs
Set Fld = Td( Fn$ ).Fields
Grid1.Cols = Fld.Count + 1
Grid1.ColWidth(0) = 600
For I = 1 To Fld.Count
Grid1.ColWidth(I) = 1500
Next I
"在網(wǎng)格的第一行內(nèi)填入字段名
Grid1.Row = 0, Grid1.Col = 0
Grid1.Text = "序號"
For I = 1 To Fld.Count
Grid1.Col = I
Grid1.Text = Fld(I - 1).Name
Next I
"在網(wǎng)格中填入相應(yīng)的數(shù)據(jù)
Ds1.MoveFirst
I = 1
Do While Not Ds1.EOF
Grid1.RowHeight(I) = 300
Grid1.Row = I
Grid1.Col = 0
Grid1.Text = I
For J = 1 To Fld.Count
Grid1.Col = J
MyNum = Ds1.Fields(J - 1).Value
"對記錄的數(shù)據(jù)類型進行判斷后做相應(yīng)的處理
If IsNumeric( MyNum ) Or IsDate( MyNum ) Then
Grid1.Text = Str$( Ds1.Fields(J - 1).Value )
Else If VarType( MyNum ) = 8 Then
Grid1.Text = Ds1.Fields(J - 1).Value
Else If VarType( MyNum ) = 0 Or VarType( MyNum ) = 1 Then
Grid1.Text = " "
End If
On Error Resume Next
Next J
Ds1.MoveNext
I = I + 1
Loop
Ds1.Close
Db1.Close
Exit Sub
最后應(yīng)記住,在VB的數(shù)據(jù)庫應(yīng)用程序運行之前,一定要在AUTOEXEC.BAT文件中加入一句SHARE.EXE /L:500。
以上所有程序均在Pentium/166機、中文Windows95下用VB4調(diào)試通過。
四、結(jié)束語
對非Access數(shù)據(jù)庫的兼容是VB數(shù)據(jù)庫編程中不可分割的重要部分。因而熟練掌握使用DAO方法對非Access數(shù)據(jù)庫的編程是極為重要的。并且,一定編程技巧的應(yīng)用也有助于彌補VB對外來數(shù)據(jù)庫支持的不足。