(一)、打开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