摘要:為了保存程序運行過程中產生的臨時數據,比較好的做法是創建動態數據庫,這既能靈活地處理各種類型格式的臨時數據,又能節省存儲空間。文章在Visual c++數據庫應用程序中,利用ADO對象連接SQL Server數據源。然后通過調用ADO對象的函數來執行SQL語句,以動態地創建SQL Server數據庫。
關鍵詞:Vc++;ADO;動態創建;SQL Server數據庫;SQL語句
0引言
在數據庫應用程序運行過程中,有時會產生一些臨時性的數據,它們可能是某個計算的中間結果,也可能是用于與其他系統進行交換的數據,或者是用于報表輸出的數據等,這些數據雖然是臨時產生并被使用的,但在使用完成之前也需要進行保存,而保存這些數據的方法不外乎兩種:用文件來保存和用數據庫來保存。若用文件來保存這些數據,則由于數據格式的原因會給數據的處理帶來不便,因而用數據庫來保存就成為一般常用的解決方法。
保存數據的數據庫一般可以事先創建也可以動態創建。事先創建是指在程序運行之前創建好數據庫,動態創建是指在程序運行過程中創建數據庫。前者方法簡便,但缺少了靈活性,因為事先創建的數據庫的結構固定,這必然限制了臨時數據的類型、格式和范圍,而且事先創建的數據庫在多數時間內有可能是閑置的,這也造成了存儲空間的浪費。較好的解決方案是在產生臨時性數據時,根據需要動態地創建數據庫以保存臨時數據,在處理完成之后刪除動態創建的數據庫。本文給出了一種動態創建數據庫的方法。
1數據庫動態創建技術
在vc++程序中動態創建數據庫,需要通過數據庫接口來實現。vc++為開發數據庫應用程序提供了多種數據庫訪問接口,主要有:ODBC(開放數據庫互連)、DAO(數據訪問對象)、OLE DB(對象鏈接與嵌入數據庫)和ADO(ActiveX數據對象)等。其中,DAO數據庫接口主要用于Access數據庫的訪問,在微軟的MFC類庫中提供了相關的DAO類(cDaoDatabase類和CDaoTableDef類),通過定義這些類的對象并調用相應的成員函數就可以實現Access數據庫和表的動態創建。對于ODBC和OLE DB訪問接口,MFC中雖然也提供了相關的類,但沒有提供用于創建數據庫和表的成員函數。
ADO是微軟極力推薦使用的最新的數據庫訪問技術,它已經成為目前數據庫開發的主流。因此,針對ADO數據庫訪問技術,如何實現sQL Server數據庫和表的動態創建,就成為編程人員較為關心的一項技術。
1.1 ADO對象
ADO對象模型包括以下幾個對象:Connection對象、Error對象、Command對象、Parameter對象、Recordset對象和Field對象,其中Connection、Command和Recordset三個對象是主體對象,它們可以被獨立創建和釋放。
Connection對象用來建立和維護與數據源的連接,對數據源的任何操作都需要一個Connection對象。Command對象用來創建和執行對數據庫的操作命令,可以使用該對象執行SQL語句或調用存儲過程,Command對象執行后將返回一個Recordset對象。Recordset對象包含執行數據庫操作后返回的—個記錄集。通過該對象可以瀏覽和更新數據庫中保存的記錄。

一個基于ADO數據庫訪問技術的應用程序通常是使用Connection對象建立與數據源的連接,然后使用Command對象給出對數據庫操作的命令,最后通過Recordset對象對結果記錄集進行瀏覽、更新等操作。
在程序中要動態創建數據庫,可以通過Connection對象來完成。首先通過該對象建立與數據源的連接,然后調用該對象的Execute函數來執行SQL語句實現數據庫的創建。
1.2創建數據庫和表的SQL語句
(1)創建數據庫的SQL語句
CREATE DATABASE語句用來創建用戶數據庫。創建一個用戶數據庫的語法格式如下:
CREATE DATABASE database_name
ON(NAME=logical file name,FILENAME=‘os—file—name',
SIZE=size,MAXSIZE=max_size I UNLIMITED,
FLIEGROWTH=growth_increment)
LOG ON(NAME=logical file name,FILENAME=os—file—name',
SIZE=size,MAXSIZE=max_sizelUNLIMITED,
FLIEGROWTH=growth_increment)
以上語法格式中,大寫的字符串是sQL關鍵字,小寫形式的字符串是實際使用時由用戶替換的參數。其中,參數database_name是要創建的數據庫名,logical_file_name是邏輯文件名,os_file_name是操作系統下的文件名和路徑,size是文件的初始容量,max_size是文件的最大容量,growth_increment是文件空間每次的增加量。在ON后面括號內的小寫字符串是數據庫文件的屬性參數,在LOG ON后面的括號內的小寫字符串是事務日志文件的屬性參數。
(2)刪除數據庫SQL語句
DROP DATABASE語句用于刪除數據庫,該語句的語法格式如下:
DROP DATABASE database_name
其中,database_name是要刪除的數據庫名。
(3)創建表的SQL語句
CREATE TABLE語句用于創建—個表,其完整語法格式較為繁瑣,在此也只說明本文實例程序中所用的語法格式。
CREATE TABLE database_name.owner.table_name
(column_namel data_type[NULLINOT NULL]
[PRIMARY KEY],
column_name2 data_type[NULLIOT NULL][PRIMARY KEY],
……
column_namen data_type[NULLINOT NULL][PRIMARY KEY])
其中,database_name是要在其中創建表的數據庫名,owner是表所有者的用戶ID,table_name是要創建的表名,column_namel—column_namen是表中的列名,data_type是列的數據類型。
(4)刪除表的SQL語句
DROP TABLE語句用于刪除表。該語句的語法格式如下:
DROP TABLE database_name.dbo.table_name
其中,database_name是要刪除的表所在的數據庫,table_name是要刪除的表名。
2動態創建數據庫的實現
2.1 ADO對象與數據源的連接
在MFC中,沒有可與ADO一起使用的類,因此,若要在Visual c++程序中使用ADO對象,首先需要導入ADO動態鏈接庫,在創建的VC工程的stdafx.h頭文件中添加如下代碼:
#import“C:\Program Files\Common Files\System\ado\
msadol 5.dll\"\no__namespace rename(“EOF”,“adoEOF”)
以上代碼的作用是告訴編譯器將動態鏈接庫文件msad015.dU引入到程序中,不使用ADO的命名空間,并且為了避免沖突,將符號常量EOF改名為adoEOF。
ADO是基于COM技術的,因此,在使用ADO對象之前必須初始化COM環境,在VC工程應用類的InitInstance成員函數中添加如下初始化COM環境的代碼:
::ColnitiaUze(NULL);
在結束ADO對象的使用后,需要調用以下代碼釋放程序占用的COM資源。在VC工程應用類的ExitInstance成員函數中添加如下代碼,將初始化的對象釋放,清除為ADO對象準備的COM環境。
::CoUninitialize():
在導入的ADO庫中包含3個基本接口:_ConnectionPtr接口、—commandPtr接口和_RecordsetPtr接口。其中,_ConnectionPtr接口用來創建一個數據源連接或執行一條不返回結果的sQL語句。因此,通過_ConnectionPtr接口執行創建數據庫的SQL語句,就可以實現動態創建數據庫。
使用ConnectionPtr接口連接數據源的步驟如下:
(1)聲明一個Connection對象指針;
(2)調用Createlnstance函數創建一個Connection對象實例;
(3)調用open函數建立到數據源的連接。
其中,聲明的Connection對象指針如果要被多個函數使用,則應將其聲明為類的成員變量。筆者的實例程序是基于對話框的應用程序,因此,將Connection對象指針聲明為主對話框類的成員。代碼如下:
-ConnectionPtr m_pConn;
建立Connection對象到數據源連接的Open函數的原型為:HRESULT Open Lbstr_t ConnectionString,一bstr—t UserlD.
_bstr_t Password,long Options);
其中,參數的含義如下:
ConnectionString:包含連接信息的字符串;
UserlD:連接到數據源的用戶ID;
Password:連接到數據源的密碼;
Options:指明連接是同步進行還是異步進行,該參數可以是如下兩個枚舉常量:adConnectUnspecified(同步)和adAsyncConnect(異步)。
在這里,需要特別說明的是ConnectionStfing參數的格式。在實際應用中,根據所用數據庫軟件的不同,ConnecfionStdng參數的格式也有所不同。以下是筆者測試通過的連接sQLServer 2000數據源的示例代碼:
m_pConn.Createlnstance(_uuidof(ConnectJon)):
m_pConn->Open('’Provider=SQLOLEDB.1:
Integrated Security=SSPI;Persist Security Info=False;
Data Source:Igtf\",.1Ill。lllI adConnectUnspecified);
其中,代碼中的lgff是SQL Server服務器名,讀者在驗證時需要根據自己的具體情況進行修改。以上代碼可以添加到主對話框類的OnlnitDialog成員函數中。
從示例代碼可以看出,ConnectionString參數的格式比較繁瑣,初學者不容易理解和掌握。不過,微軟為我們提供了一種可視化的解決方法,就是使用通用數據連接文件來建立和測試ADO的連接屬性。數據連接文件的使用方法是:
(1)在VC工程文件夾中新建一個文本文件,然后將該文.件的擴展名改為udl;
(2)雙擊該文件打開“數據鏈接屬性”對話框,在“提供程序”標簽頁中選擇Microsoft OLE DB Provider for Server項,如圖l所示。
(3)在“連接”標簽頁中,選擇或輸入SQL Server 2000服務器名稱,如圖2所示。
(4)單擊“連接”標簽頁中的“測試連接”按鈕,測試連接屬性設置是否正確,若彈出的對話框中顯示“測試連接成功”,則單擊“確定”按鈕完成數據連接文件的設置。
數據連接文件設置完成后,就可以將前面Open函數的調用代碼改為:
m._pConn->Open(“File Name=mydata.udl”,””,””,
adConnectUnspecified);
使用數據連接文件的好處不僅僅是簡化了連接屬性的設置,還有利于數據庫應用程序在用戶機器上的安裝和調試。當我們將開發好的數據庫應用程序安裝到用戶機器上時,由于運行環境發生了改變,有時就需要重新修改程序代碼進行連接調試。如果我們使用數據連接文件來設置連接屬性,則在程序安裝到用戶機器上后,只需要重新設置一下數據連接文件,而不用修改程序就可以正常運行了。
在應用程序中,一般在使用完成數據庫后,應該關閉與數據源的連接。ADO在關閉連接的同時,也將關閉所有使用這個連接的ADO對象。關閉連接的代碼如下:
m_pConn->Close():
m_pConn=NULL;
以上代碼可以添加到主對話框類的OnDestroy成員函數中。
2.2用SQL語句創建數據庫和表
調用ADO對象模型中的Connection對象的Execute函數執行sQL語句,可以實現對數據源的相關操作。該函數的原型如下:
_RecordsetPtr Execute (_bstr_t CommandText,
VARIANTRecordsAffected,long Options);
其中,參數CommandText用于給出要執行的SQL語句,RecordsAffected是執行命令后的返回值,表明符合命令的行數,Options用于指定命令的類型。
如果要想創建數據庫和表,則只要在調用Execute函數時,第1個參數給出創建數據庫和表的sQL語句即可。示例代碼如下:
_bstr_t strSQL(\"CREATE DATABASE student
ON(NAME=student,
FILENAME=\'C:\\Pmgmm Files\\Microsoft SQL
Server\\MSSQL\\data\\student_data.mdff)
LOG ON(NAME:student_log,
FILENAME=VC:\\Program Files\\Microsoft SQL
Server\\MSSQL\\data\\student_log.IdfV)”);
try{
m_pConn->Execute(strSQL,NULL,adCmdText);
}
catch Lcom_error&e){
MessageBox(e.ErrorMessage()):
}
以上示例代碼是創建—個名為student的數據庫。SQL語句中沒有指定數據庫文件和事務日志文件的初始容量,則默認為1MB;沒有給出兩個文件的最大容量,則默認為UNLIMITED。即增長到硬盤滿為止;沒有給出文件的增量,則默認為10%。
創建表的示例代碼如下:
_bstr_t strSQL(“create table student.dbo.用戶表(
用戶名varchar(10)NO l NULL PRIMARY KEY.
密碼varchar(16)NOT NULL,權限 integer)”):
try{
m_pConn->Execute(strSQL,NULL,adCmdText);
}
catch(_com_errore){
MessageBox(e.ErrorMessage()):
}
以上代碼是在student數據庫中創建一個名為“用戶表”的表,該表有3個列:“用戶名”、“密碼”和“權限”,其中“用戶名”為主鍵,“用戶名”和“密碼”不能為空。
2.3用SQL語句刪除數據庫和表
刪除數據庫和表的SQL語句的語法相對較為簡單,刪除student數據庫的示例代碼如下:
bstr_t strSQL(\"DROP DATABASE student\"};
try{
m_pConn->Execute(strSQL,NULL.adCmdText);
}
catch(_-com_error&e){
MessageBox(e.ErrorMessage()):
}
刪除“用戶表”的示例代碼如下:
bstr_t strSQL(”DROP TABLE student.dbo.用戶表”):
try{
m_pConn->Execute(strSQL.NULL。adCmdText);
}
catch L-com_errore){
MessageBox(e.ErrorMessage()):
}
3結束語
本文探討了利用ADO的Connection對象來連接數據源,然后通過調用Connection對象的Execute函數來執行sQL語句,實現SQL Sewer 2000數據庫動態創建的方法。讀者可以參照文中介紹的方法,或將所列的示例代碼添加到自己的應用程序中,即可在自己的應用程序中實現數據庫的動態創建。文中雖然針對的是Visual c++編程工具和sQL Sewer 2000數據庫,但動態創建數據庫和表的原理是一樣的,讀者只要理解了文中介紹的編程技術,也同樣可以使用其他編程工具(如Visual Basic)來實現sQL Server 2000數據庫或其他常見關系型數據庫(如Oracle)的動態創建。動態創建的數據庫的訪問方法則與其他事先建立的數據庫的訪問方法相同。
(注:本文中所涉及到的圖表、注解、公式等內容請以PDF格式閱讀原文。)