1.开放数据库连接(ODBC API):提供了一个通用的编程接口,允许程序与多种不同的数据库连接。它为Oracle,SQL Server,MS Excel等都提供了驱动程序,使得用户可以使用SQL语句对数据库进行直接的底层功能 *** 作。在使用ODBC API时,用户须引入的头文件为 "sql.h ", "sqlext.h ", "sqltypes.h "。用ODBC API创建数据库应用程序遵循一定的基本步骤:
第一步是分配ODBC环境,使一些内部结构初始化。完成这一步,须分配一个SQLHENV类型的变量在ODBC环境中做句柄使用。
第二步是为将要使用的每一个数据源分配一个连接句柄,由函数SQLALLocHandle()完成。
第三步是使用SQLConnect()把连接句柄与数据库连接,可以先通过SQLSetConnectAttr()设置连接属性。
然后就可以进行SQL语句的 *** 作,限于篇幅,相关的函数就不具体介绍了,读者可以参考相关书籍。
*** 作完成后,用户取回相应的结果,就可以取消与数据库的连接。
最后需要释放ODBC环境。
ODBC API的特点是功能强大丰富,提供了异步 *** 作,事务处理等高级功能,但相应的编程复杂,工作量大。
2.MFC ODBC类:MFC1.5后的版本里引入封装了ODBC功能的类。通过这些类提供与ODBC的接口,使得用户可以不须处理ODBC API中的繁杂处理就可以进行数据库 *** 作。主要的MFC ODBC类如下。
CDatabase类:一个CDatabase对象表示一个到数据源的连接,通过它可以 *** 作数据源。应用程序可使用多个CDatabase对象:构造一个对象并调用OpenEx()成员函数打开一个连接。接着构造CRecordSet对象以 *** 作连接的数据源,并向CDatabase对象传递记录集构造程序指针。完成使用后用Close()成员函数销毁CDatabase对象。一般情况下并不需要直接使用CDatabase对象,因为CRecordSet对象可以实现大多数的功能。但是在进行事务处理时,CDatabase就起到关键作用。事务(Transaction)指的是将一系列对数据源的更新放在一起,同时提交或一个也不提交,为的是确保多用户对数据源同时 *** 作时的数据正确性。
CRecordSet类:一个CRecordSet对象代表一个从数据源选择的一组记录的集合-记录集。记录集有两种形式:snapshot和dynaset。前者表示数据的静态视图,后者表示记录集与其他用户对数据库的更新保持同步。通过CRecordSet对象,用户可以对数据库中的记录进行各种 *** 作。
CRecordView类:CRecordView对象是在空间中显示数据库记录的视图。这种视图是一种直接连到一个CRecordSet对象的格式视图,它从一个对话框模板资源创建,并将CRecordSet对象的字段显示在对话框模板的控件里。对象利用DDX和RFX机制,使格式上的控件和记录集的字段之间数据移动自动化,也就是说,用户甚至不要编写一行代码就可以实现简单的数据库记录查看程序。
CDBException类:由Cexception类派生,以三个继承的成员变量反映对数据库 *** 作时的异常:
m_nRetCode:以ODBC返回代码(SQL_RETURN)的形式表明造成异常的原因。
m_strError:字符串,描述造成抛出异常的错误原因。
m_strStateNativeOrigin:字符串,用以描述以ODBC错误代码表示的异常错误。
MFC数据库类成员函数都能抛出CDBException类型的异常,所以在代码对数据库进行 *** 作后监测异常是正确做法。
MFC ODBC类在实际开发中应用最广,因为它功能丰富, *** 作相对简便。
3.MFC DAO(数据访问对象)编程:DAO用于和微软的Access数据库接口。在数据库应用程序如果只需与Access数据库接口时,使用DAO编程较方便。其主要类如下。
CDaoWorkspace:CDaoWorkspace对象可以让一个用户管理从登陆到离开期间,指定的密码保护的数据库会话全过程。大多数情况下不要多个工作区也不要创建明确的工作区对象。因为在打开数据库和记录集对象时,它们可以使用DAO缺省工作区。
CDaoDatabase:代表一个连接,类似上述CDatabase类。
CDaoRecordSet:用来选择记录集并 *** 作,类似上述CRecordSet类。
CDaoRecordView:类似上述CRecordView类。
CDaoException:类似上述CDBException类。
CDaoTableDef:表示基本表或附加表的定义。每个DAO数据库对象包括一个称为TableDef的收集,包含所有存储的DAO表定义对象。CDaoTableDef对象可以用来控制表定义。
CDaoQueryDef:CDaoQueryDef对象表示了一个查询定义(querydef)。
CDaoFieldExchange:支持数据库类使用的DAO字段交换(DFX)例程。也可处理事务,类似MFC ODBC类。
MFC DAO仅用来支持Access数据库,应用范围相对固定。
4.OLE DB:OLE DB在数据提供程序和用户之间提供了灵活的组件对象模型(COM)接口,这种灵活性有时会使得 *** 作复杂化。OLE DB框架定义了应用的三个基本类。
数据提供程序Data Provider:拥有自己的数据并以表格形式显示数据的应用程序。提供OLE DB的行集COM接口,期显示范围可以从单一数据表格的简单提供者知道更复杂的分布式数据库系统。
使用者Consumers:使用OLE DB接口对存储在数据提供程序中的数据进行控制的应用程序。用户应用程序归为使用类。
服务提供程序Service Provider:是数据提供程序和使用者的组合。服务提供程序没有自己的数据,但使用
OLE DB使用者接口来访问存储在数据提供程序中的数据。然后,服务提供程序通过打开数据提供程序接口使得数据对使用者有效。服务提供程序常用于向应用程序提供高层次服务,比如高级分布式查询。
OLE DB编程时,用户使用组件对象开发应用程序。这些组件有:
枚举器:用于列出可用的数据源;
数据源:代表单独的数据和服务提供程序,用于创建对话;
对话:用于创建事务和命令;
事务:用于将多个 *** 作归并为单一事务处理;
命令:用于向数据源发送文本命令(SQL),返回行集;
错误:用于获得错误信息。
5.ActiveX数据对象(ADO):是微软提供的面向对象的接口,与OLE DB类似,但接口更简单,具有更广泛的特征数组和更高程度的灵活性。ADO基于COM,提供编程语言可利用的对象,除了面向VC++,还提供面向其他各种开发工具的应用,如VB,VJ等。ADO在服务器应用方面非常有用,特别是对于动态服务器页面ASP(Active Server Page)。
ADO对象结构类似于OLE DB,但并不依靠对象层次。大多数情况下,用户只需要创建并只使用需要处理的对象。下面的对象类组成了ADO接口。
Connection:用于表示与数据库的连接,以及处理一些命令和事务。
Command:用于处理传送给数据源的命令。
Recordset:用于处理数据的表格集,包括获取和修改数据。
Field:用于表示记录集中的列信息,包括列值和其他信息。
Parameter:用于对传送给数据源的命令之间来回传送数据。
Property:用与 *** 作在ADO中使用的其他对象的详细属性。
Error:用于获得可能发生的错误的详细信息。
在VC++使用ADO需要进行COM *** 作,详细方法在此就不赘述了。
在当今流行的分布式开发环境下,VC++6.0在数据库开发方面有较强的优势,学会
在不同的场合选用不同的技术,对开发人员来说是必要的技术。
我感觉现在利用ADO比较多,这个方法连接数据库比较灵活。ODBC也可以。但是需要创建数据源有时候你要将这个程序换地方可能就会导致找不到数据源从而连接不上数据库,我建议你利用ADO的。以下代码同时兼容WINDOWS / MFC / LINUX / ODBC / MYSQL#ifdef WIN32
#include <windows.h>
#include <odbcinst.h>
#include <sqlext.h>
#else
#include <mysql.h>
#include <unistd.h>
#define SQLHANDLE static MYSQL
#endif
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
SQLHANDLE hDBEnv, hDBC
int DB_Open(char * dbcn, char * usr, char * pwd)
{
int r
#ifdef WIN32
r = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &hDBEnv)
if(r) return 0
r = SQLSetEnvAttr(hDBEnv,SQL_ATTR_ODBC_VERSION,
(void*)SQL_OV_ODBC3,0)
if(r) return 0
r = SQLAllocHandle(SQL_HANDLE_DBC, hDBEnv, &hDBC)
if(r) return 0
r = SQLConnect(hDBC,
(unsigned char *)dbcn, strlen(dbcn),
(unsigned char *)usr, strlen(usr),
(unsigned char *)pwd, strlen(pwd))
return r==SQL_SUCCESS || r==SQL_SUCCESS_WITH_INFO
#else
mysql_init(&hDBC)
MYSQL * rx = mysql_real_connect(
&hDBC, dbcn, usr, pwd, NULL, 0, NULL, 0)
if(!rx) return 0
return 1
#endif
}//end DB_Open
int DB_Exec(char * sql)
{
#ifdef WIN32
SQLHANDLE hStatement = NULL
SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &hStatement)
SQLExecDirect(hStatement,(unsigned char *)sql, strlen(sql))
SQLCloseCursor(hStatement)
SQLFreeHandle(SQL_HANDLE_STMT, hStatement)
hStatement = NULL
#else
mysql_real_query (&hDBC, sql, strlen(sql))
#endif
return 1
}//end DB_Exec
int DB_Close(void)
{
#ifdef WIN32
SQLDisconnect(hDBC)
SQLFreeHandle(SQL_HANDLE_DBC, hDBC)
SQLFreeHandle(SQL_HANDLE_ENV, hDBEnv)
#else
mysql_close(&hDBC)
#endif
return 1
}//DB_Close()
#ifndef WIN32
typedef struct tagMySQLRecordset {
MYSQL_RES * hRecord
void * * row
int * size
int cols
} MYSQLRecordset
#endif
void DB_CleanQuery(void *hRecordset)
{
if(!hRecordset) return
#ifdef WIN32
__try {
SQLCloseCursor(hRecordset)
SQLFreeHandle(SQL_HANDLE_STMT, hRecordset)
hRecordset = NULL
}__finally{
return
}//end try
#else
MYSQLRecordset * hRec = (MYSQLRecordset *) hRecordset
mysql_free_result (hRec->hRecord)
free(hRec->row) hRec->row = NULL
free(hRec->size)hRec->size = NULL
free(hRec)hRec = NULL
#endif
}//end DB_CleanQuery
int DB_Next(void * hRecordset)
{
int r=0if(!hRecordset) return 0
#ifdef WIN32
r = SQLFetch(hRecordset)
r = r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO
if(!r) {
DB_CleanQuery(hRecordset)
}//end if
#else
MYSQLRecordset * hRec = (MYSQLRecordset *) hRecordset
MYSQL_ROW row = mysql_fetch_row (hRec->hRecord)
if(row) {
for(int i=0i<hRec->colsi++) {
memcpy(hRec->row[i], row[i], hRec->size[i])
}//next i
r = 1
}else{
DB_CleanQuery(hRecordset)
r = 0
}//end if
#endif
return r
}//end DB_Next
int DB_params_count(const char * fmt)
{
int i=0, j=0
while(fmt[i]) {
if(fmt[i]=='%') j++
i++
}//end while
return j
}//end DB_params_count
void * DB_Query(char *sql, const char *fmt, ...)
{
int r=0
int cols = DB_params_count(fmt)
if(cols<1) return NULL
#ifdef WIN32
SQLHANDLE hStatement = NULL
SQLAllocHandle(SQL_HANDLE_STMT, hDBC, &hStatement)
r = SQLExecDirect(hStatement,(unsigned char *)sql, strlen(sql))
r = r==SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO
if(!r) {
return NULL
}//end if
#else
r = mysql_real_query (&hDBC, sql, strlen(sql))
if(r) return NULL
MYSQL_RES * rec = NULL
rec = mysql_store_result (&hDBC)
if(!rec) return NULL
MYSQLRecordset * hStatement
= (MYSQLRecordset *)malloc(sizeof(MYSQLRecordset))
if(!hStatement) return NULL
memset(hStatement, 0, sizeof(MYSQLRecordset))
hStatement->hRecord = rec
hStatement->cols = cols
hStatement->row = (void **)malloc(cols * sizeof(void *))
memset(hStatement->row, 0, cols * sizeof(void *))
hStatement->size = (int *)malloc(cols * sizeof(int))
memset(hStatement->size, 0, cols * sizeof(int))
#endif
va_list apva_start(ap, fmt)
void * varchar buf[32]
int i=0,j=0,k=0,sz=0char c=0
int len = strlen(fmt)int bad=1
#ifdef WIN32
int col=1
#else
int col=0
#endif
while(fmt[i]) {
c = fmt[i++]
if(c != '%') continue
c = fmt[i++]
var = va_arg(ap, void *)
if(c == 'd') {
#ifdef WIN32
SQLBindCol(hStatement, col, SQL_C_SLONG, var, 4,NULL)
#else
hStatement->row[col] = var
hStatement->size[col] = sizeof(long)
#endif
col++
continue
}//end if
if(c == 'f') {
#ifdef WIN32
SQLBindCol(hStatement, col, SQL_C_FLOAT, var, 4,NULL)
#else
hStatement->row[col] = var
hStatement->size[col] = sizeof(float)
#endif
col++
continue
}//end if
memset(buf, 0, 32)bad=1
for(j=i-1j<lenj++) {
c = fmt[j]
if(c>='0' &&c<='9') buf[j-i+1]=c
if(c=='s') {bad=0k=j+1break}
}//next j
if(bad) return NULL
sscanf(buf, "%d", &sz)
#ifdef WIN32
SQLBindCol(hStatement, col, SQL_C_CHAR, var, sz, NULL)
#else
hStatement->row[col] = var
hStatement->size[col] = sz
#endif
col++
i = k
}//end while
va_end(ap)
return hStatement
}//end DB_Rec
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)