第一章:如何為你的開發系統配置DSN:
(一)、打開Windows的控制面板。選擇ODBC Data Sources圖標,雙擊打開此圖標內容,此時出現ODBC Data Source Administrator對話框。
(2)、在對話框中選擇User DSN然後你可以選擇<添加>按鈕來新增一個DSN.
第二章:如何利用ODBC API在VC下面直接編寫基於數據庫的程序:
ODBC數據庫編程
一、 一般步驟:
分配環境
應用系統在調用任何ODBC函數之前,首先必須初始化ODBC,並建立一個環境。
ODBC用該環境監視應用系統已經建立的數據庫連接。每個應用系統只建立一個
環境是很有必要的,因為不管有多少連接都可以在一個環境中建立。完成這一分
配過程的ODBC函數SQLAllocEnv在下一小節描述。
SQLAllocEnv
SQLAllocEnv為環境句柄分配內存,並初始化應用系統使用的ODBC調用層接口。
應用系統在調用任何其他ODBC函數之前必須調用SQLAllocEnv。
以下是SQLAllocEnv的語法:
RETCODE SQLAllocEnv(phenv)
SQLAllocEnv的參數如下表所示,其返回碼是SQL-ERROR。因為調用SQLError
時無有效句柄,所以該函數沒有SQLSTATE返回碼;
//分配環境句柄
SQLRETURN m_retcode;
if( m_henv != SQL_NULL_HENV )
return FALSE;
if (SQL_SUCCESS == (m_retcode = SQLAllocEnv( &m_henv )))
{
//創建新的DSN
CreateDSN(IDS_HOME_DSNNAME,IDS_HOME_DBFILENAME);
//分配連接句柄
if (SQL_SUCCESS == (m_retcode = SQLAllocConnect( m_henv, &m_hdbc )))
{
// 連接數據源
if (SQL_SUCCESS == (m_retcode = SQLConnect( m_hdbc, (UCHAR *)((LPCTSTR)m_strDSN), SQL_NTS, NULL, 0, NULL, 0 )))
{
m_bConnected = TRUE;
}
}
}
分配連接句柄
就象應用系統的環境由環境句柄代表一樣,連接句柄代表應用系統與數據源
之間的連接。對於應用系統所要連接的每一個數據源而言,都必須分配一個連接
句柄。例如,如果需要同時與dBase和BTrieve的數據源連接,必須分配兩個連接
句柄。下一小節描述函數SQLAllocConnect.
SQLAllocConnect在henv標識的環境裡為連接句柄分配內存。以下是
SQLAllocConnect的語法:
RETCODE SQLAllocConnect(henv,phdbc)
SQLAllocConnect 的參數如下表所示,其返回碼是:
SQL-SUCCESS
SQL-SUCCESS-WITH-INFO
SQL-ERROR
SQL-INVALID-HANDLE
SQLSTATE的返回碼是:
01000 S1000 S1001 S1009
利用核心函數與數據源連接
盡管有很多ODBC函數可以建立連接,但在核心API層卻只有一種,即函數
SQLConnect。它提供簡單、有效的方法與數據源的連接。所有驅動程序都支持
SQLConnect,所以它是最具有互用性的解決方案。下面是SQLConnect的描述。
SQLConnect加載一個數據庫驅動程序,並建立一個與數據源的連接。該連接
句柄確定所有連接信息(包括它的狀態,事務狀態和錯誤信息)的存儲位置。
SQLConnect的語法如下:
RETCODE SQLConnect(hdbc,szDSN,cbDSN,szUID,cbUID,szAuthStr,cbAuthAtr)
SQLConnectde的返回碼是:
SQL-SUCCESS
SQL-SUCCESS-WITH-INFO
SQL-ERROR
SQL-INVALID-NUMBER
與數據源斷開
應用系統一旦使用完成一個數據源連接,便應與之斷開。連接是十分昂貴
的資源,因為很多DBMS對同時連接的每一個許可人員或用戶都是收費的。當
連接完成時,應當把它返回,以便其它用戶能注冊進入該系統。下面描述的ODBC
函數SQLDisconnect處理這一操作過程。
SQLDisconnect關閉與指定的連接句柄相關的數據源連接。SQLDisconnect
的語法如下:
RETCODESQLDisconnect(hdbc)
SQLDisconnect的返回碼是:
SQL-SUCCESS
SQL-SUCCESS-WITH-INFO
SQL-ERROR
SQL-INVALID-HANDLE
如果數據源連接成功的話,就可以繼續下一步;
CString strSQLString;
RETCODE ReturnCode;
SQLHSTMThstmt;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT,theApp.m_hdbc,&hstmt))
return;
strSQLString.Format(
"SELECT "
"NID,"
"ARIQI,"
"NJINE,"
"ASHUOMING,"
"ALAIYUAN,"
"ACUNZHE,"
"AYONGTU,"
"AXIAOFEI,"
"ABEIZHU"
" FROM HHZhiChu "
" WHERE NID=%u",
nID);
if (SQL_SUCCESS == (ReturnCode = SQLExecDirect(hstmt,(UCHAR*)((LPCTSTR)strSQLString),SQL_NTS)))
{
SQLBindCol(hstmt,1,SQL_C_SLONG,&dbdata.m_Nid,0,&cb);
SQLBindCol(hstmt,2,SQL_C_TIMESTAMP,&dbdata.m_Ariqi,0,&cb);
SQLBindCol(hstmt,3,SQL_C_DOUBLE,&dbdata.m_Njine,0,&cb);
SQLBindCol(hstmt,4,SQL_C_CHAR,dbdata.m_Ashuoming,HHZhiChu_aShuoMing_SIZE,&cb);
SQLBindCol(hstmt,5,SQL_C_CHAR,dbdata.m_Alaiyuan,HHZhiChu_aLaiYuan_SIZE,&cb);
SQLBindCol(hstmt,6,SQL_C_CHAR,dbdata.m_Acunzhe,HHZhiChu_aCunZhe_SIZE,&cb);
SQLBindCol(hstmt,7,SQL_C_CHAR,dbdata.m_Ayongtu,HHZhiChu_aYongTu_SIZE,&cb);
SQLBindCol(hstmt,8,SQL_C_CHAR,dbdata.m_Axiaofei,HHZhiChu_aXiaoFei_SIZE,&cb);
SQLBindCol(hstmt,9,SQL_C_CHAR,dbdata.m_Abeizhu,HHZhiChu_aBeiZhu_SIZE,&cb);
if (SQL_SUCCESS == (ReturnCode = SQLFetch(hstmt)))
{
//讀數據成功,可一對數據進行處理了。
}
}
::SQLFreeHandle(SQL_HANDLE_STMT,hstmt);
程序完了後要關閉數據庫,
//斷開連接
if (m_bConnected)
{
SQLDisconnect(m_hdbc);
SQLFreeHandle(SQL_HANDLE_DBC,m_hdbc);
m_hdbc = NULL;
}
//刪除DSN
if (FoundDSNName(IDS_HOME_DSNNAME))
DeleteDSN(IDS_HOME_DSNNAME);
//刪除環境句柄
if (m_henv)
{
SQLFreeHandle(SQL_HANDLE_ENV,m_henv);
m_henv = NULL;
}
二、 針對數據庫的操作
以下的方法只對ACCESS數據庫有效,
1、 生成數據庫
CString strFileName="c:1.mdb";
CString strDriver;
char szFileName[100+_MAX_PATH];
strDriver = "Microsoft Access Driver (*.mdb)";
sprintf(szFileName,"CREATE_DB=%s General",strFileName);
SQLConfigDataSource(NULL,ODBC_ADD_DSN,strDriver,szFileName);
2、 壓縮數據庫
BOOL SuperDatabase::Compaction(CString strSourName, CString strDestName)
{
if (strSourName.IsEmpty())
return FALSE;
if (strDestName.IsEmpty())
strDestName = strSourName;
char szCommand[100+_MAX_PATH];
int j;
CString strDriver;
strDriver = "Microsoft Access Driver (*.mdb)";
j = sprintf(szCommand,"COMPACT_DB=%s %s General",strSourName,strDestName);
return SQLConfigDataSource(NULL,ODBC_ADD_DSN,strDriver,szCommand);
}
3、 取得數據庫的名稱:
如果已經打開了一個數據源,可以通過數據源來取得當前的數據庫的名稱;
CString SuperDatabase::GetDatabaseName()
{
ASSERT(m_hdbc != SQL_NULL_HDBC);
char szName[MAX_TNAME_LEN];
SWORD nResult;
SQLGetInfo(m_hdbc, SQL_DATABASE_NAME,
szName, MAX_TNAME_LEN, &nResult);
return szName;
}
三、 針對數據源的操作:
1、 增加數據源
BOOL SuperDatabase::CreateDSN(CString strDriver, CString strFileName,CString strDSN, CString strUserID, CString strPWD)
{
char szAttr[100+_MAX_PATH];
int j;
if (strDriver.IsEmpty())
strDriver = "Microsoft Access Driver (*.mdb)";
j = sprintf(szAttr,"DSN=%s",strDSN);
j++;
j = sprintf(szAttr+j,"DBQ=%s ",strFileName);
return SQLConfigDataSource(NULL,ODBC_ADD_DSN,strDriver,szAttr);
}
2、 刪除數據源
void SuperDatabase::RemoveDSN(CString strDSN)
{
char szDSN[255];
sprintf(szDSN,"DSN=%s",strDSN);
BOOL bIsSuccess = SQLConfigDataSource(NULL,ODBC_REMOVE_DSN,"Microsoft Access Driver (*.mdb)",szDSN);
}
3、 取得系統已有得DSN
SWORD nDataSourceNameLength; //DSN str length
SWORD nSourceDescriptionLength; //Driver Description str length
char szSourceDescription[MAXBUFLEN+1]; //Driver Description string
SQLRETURN nResult; //Return Code
SWORD nDirection=SQL_FETCH_FIRST;
if ((nResult = SQLDataSources(m_henv, nDirection, (UCHAR *)((LPCTSTR)strDataSourceName), MAXBUFLEN, &nDataSourceNameLength, (UCHAR *)szSourceDescription, MAXBUFLEN, &nSourceDescriptionLength)) != SQL_NO_DATA && nResult != SQL_ERROR)
{
nDirection=SQL_FETCH_NEXT;
// szSourceDescription為DSN 的描述,可以在這裡取來用;
}
四、 針對表的操作:
1、 取得表名:
void SuperDatabase::GetTable(CStringList &tableList)
{
ASSERT(m_bIsConnect);
if (!m_bIsConnect)
return;
SQLHSTMT hstmt = NULL;
if (SQL_SUCCESS == ::SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &hstmt))
{
if (SQL_SUCCESS == ::SQLTables(hstmt, NULL, 0, NULL, 0,
NULL, 0, NULL, 0))
{
SDWORD cb;
char szTable[255];
char szTableType[255];
::SQLBindCol(hstmt, 3, SQL_C_CHAR, szTable, 255, &cb);
::SQLBindCol(hstmt, 4, SQL_C_CHAR, szTableType, 255, &cb);
wh