10.9 自動註冊DSN和建立表
在開始編寫自己的資料庫應用程式時,讀者很快會遇到兩個令人頭痛的問題。一是在訪問ODBC資料來源前,必須在ODBC管理器中手工註冊DSN(資料來源名)。這樣的應用程式要求使用者作額外的工作,顯得很不專業。另一個問題是AppWizard和ClassWizard並不支援表的建立,程式員似乎必須先用DBMS建立好表,然後才能使用。如果一個資料庫應用程式不能自己建立表,那麼它的功能將大打折扣。
事實上,通過一些技巧,可以使應用程式能夠對使用者透明地註冊DSN並任意建立表。本節的目的就是教會讀者如何解決這兩個問題。在下面幾個小節中,分別提供了ODBC和DAO的解決方案。
10.9.1 自動註冊DSN
無論是用ODBC還是DAO類,在訪問ODBC資料來源以前,都必須先註冊DSN。通過調用函數SQLConfigDataSource,可以實現自動註冊DSN。當然,用DAO可以直接存取一些常用的資料庫,而不必通過ODBC來訪問(參見10.8.3)。
清單10.14的代碼示範了註冊DSN的過程。該段代碼先用SQLConfigDataSource註冊一個名為MYDB的FoxPro 2.5資料來源,然後調用CDatabase::Open函數與該資料來源串連。注意在使用這段代碼時,要包含afxdb.h標頭檔,讀者可以把該檔案放到stdafx.h中。
清單10.14 自動註冊DSN
#include “afxdb.h”
. . .
CDatabase db;
if(!SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft FoxPro Driver (*.dbf)",
"DSN=MYDB/0"
"DefaultDir=c://mydir/0"
"FIL=FoxPro 2.5/0"
"DriverId=280/0"))
{
AfxMessageBox("Can't add DSN!");
return ;
}
TRY
{
db.Open("MYDB");
}
CATCH(CDBException, e)
{
AfxMessageBox(e->m_strError);
return;
}
END_CATCH
在註冊DSN時,SQLConfigDataSource函數的第二個參數應該是ODBC_ADD_DSN,第三個參數指定了ODBC驅動程式,它的寫法可以參照ODBC管理器的驅動程式頁。第四個參數說明了資料來源的各種屬性,它是由一系列子串構成,每個子串的末尾必須有一個“/0”。最重要的屬性是“DSN=資料來源名”,其它屬性包括預設目錄以及驅動程式版本資訊。在上例中,使用FoxPro 2.5的版本,所以DriverId應該是280,對應地,FoxPro 2.6的DriverId是536,FoxPro 2.0的是24。
如果讀者對SQLConfigDataSource函數的第四個參數的設定方法不清楚,那麼可以開啟Windows的註冊表看一看登入過的DSN的各項屬性。運行RegEdit可以開啟註冊表,然後依次開啟HKEY_CURRENT_USER->Software->ODBC->ODBC.INI,就可以看到登入的DSN,開啟各DSN,則可以看到該DSN的各項屬性,讀者可以仿照DSN屬性來設定第四個參數。
DSN的名字必須唯一,因此如果要註冊的DSN已被註冊過,那麼SQLConfigDataSource就修改原來DSN的屬性。
10.9.2 用ODBC建立表
由於ODBC類不支援DDL,所以只有通過ODBC API來建立表。程式需要調用Cdatabase :: ExecuteSQL來直接執行SQL語句。
清單10.15給出了建立表的一個例子,該程式先自動註冊了一個名為MYDB的FoxPro 2.5資料來源,然後建立了一個名為OFFICES的表(OFFICES.DBF檔案),在這個表中有OfficeID和OfficeName兩個TEXT型欄位,長度分別為4和10個位元組。注意,如果要使用這段代碼,則需要包含afxdb.h和odbcinst.h。
清單10.15 ODBC建立表的例子
#include “afxdb.h”
#include "odbcinst.h"
. . .
CDatabase db;
if(!SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Microsoft FoxPro Driver (*.dbf)",
"DSN=MYDB/0"
"DefaultDir=c://mydir/0"
"FIL=FoxPro 2.5/0"
"DriverId=280/0"))
{
AfxMessageBox("Can't add DSN!");
return ;
}
TRY
{
db.Open("MYDB");
db.ExecuteSQL("CREATE TABLE OFFICES (OfficeID TEXT(4)"
",OfficeName TEXT(10))"); }
CATCH(CDBException, e)
{
AfxMessageBox(e->m_strError);
return;
}
END_CATCH
ExecuteSQL執行了一個實實在在的SQL語句CREATE來建立表,看來使用者應該找本SQL方面的書研究研究。要注意一個資料庫中的表名必須是唯一的,如果要建立的表已經存在,則ExecuteSQL會產生一個異常。
10.9.3 用DAO建立表
由於DAO類直接支援DDL,所以用DAO類建立表比ODBC容易。DAO的CDaoTableDef類提供了對錶的結構的定義,該類提供了建立表的成員函數。
清單10.16示範了一段用DAO類建立表的例子。注意,若要使用這段代碼,則應該包含afxdao.h標頭檔。在該例中,先與一個FoxPro 2.5資料庫連接(實際上是一個目錄),然後再構建一個CDaoTableDef對象,接著調用CDaoTableDef :: Create函數建立一個名為STUDENTS的表(STUDENTS.DBF),調用CDaoTableDef :: CreateField為該表建立了兩欄位,欄位名分別是ID和NAME,類型分別是Integer和dbText,欄位的長度分別為2和10個位元組。最後調用CDaoTableDef :: Append把新建立的表儲存到資料庫中。
清單
10.16 DAO建立表的例子
#include
“afxdao.h”
. . .
CDaoDatabase daoDb;
try
{
daoDb.Open("",FALSE,FALSE,"FoxPro 2.5;DATABASE=d://zwin");
CDaoTableDef table(&daoDb);
table.Create("STUDENTS");
table.CreateField("ID",dbInteger,2);
table.CreateField("NAME",dbText,10);
table.Append();
}
catch(CDaoException* e)
{
AfxMessageBox(e->
m_pErrorInfo->m_strDescription);
e->Delete();
return FALSE;
}
關於CDaoDatabase :: Open的說明請參見10.8.3。注意一個資料庫中的表名必須是唯一的,如果要建立的表已經存在,則CDaoTableDef :: Create會產生一個異常。