ODBC的基本介绍
ODBC是为数据库应用程序访问关系型数据库时提供的一个统一的接口,对于不同的数据库ODBC提供了一套统一的API,使应用程序可以访问任何一种提供了ODBC驱动程序的数据库。但是ODBC只能用于关系型数据库,这就使得利用ODBC很难访问对象型数据库及其他非关系型数据库。
这种方法也是我目前所知道的C++访问数据库的5中方法中的最简单的一种,实际上,因为所用到的开发工具是Visual C++6.0,所以更准确的说应该是MFC ODBC。
常用的类有:CDatabase数据库类、CRecordset记录集类、CRecordView可视记录集类和CDBException异常类。
1)CDatabase类对象建立了和数据库数据源的一个连接,通过它可以对数据库进行操作。
2)CRecordset类对象代表从一个从数据源中获取的记录集。有两种重要的打开方式,分别为Dynaset(动态集)和Snapshot(快照集)。Snapshot提供了对数据库的静态访问,就像对数据源的某些数据进行拍照一样,是静态的数据,别的用户对数据源的数据进行添加、修改、删除的时候,快照集里面的记录不受影响,只有在调用了CRecordset的Requery函数重新查询的时候,快照集才会产生改变。而Dynaset(动态及)则提供了对数据库的动态访问,和其他用户所作的更改保持同步,当别的用户修改或删除了记录集中的记录时,会在动态集中反应出来。
3)CRecordView类对象提供了一个表单视图来显示和操作记录集,因为CRecordView类派生于CFormView类,同时又绑定了一个记录集,从而可以利用表单视图方便地显示、修改、添加和删除记录。CRecordView采用对话框数据交换技术(DDX)和记录字段交换技术(RFX)自动实现表单控件中的数据和数据库中的字段数据的关联。
4)CDBException类对象处理MFC ODBC访问类在操作数据库的时候发生的一样,它继承与CException类。MFC ODBC在操作数据库的时候可能会抛出CDBException异常,这些异常一定要记得处理,否则后果会很严重!
实际应用的过程:
1、首先要引入MFC ODBC数据库类的定义文件,为了防止反复的#include可以在工程下的StdAfx.h头文件中使用#include文件,这样就一劳永逸,之后就不用再在其他的文件中使用#include了。
2、对数据源进行操作之前需要定义一个CDatabase对象。代码如下:CDtabase m_db;
3、然后利用CDatabase类的OpenEx函数建立和数据库的连接。函数原型如下:
virtual BOOL OpenEx(LPCTSTR lpszConnectString,DWORD dwOptions=0);throw(CDBExcaption,CMemoryException);
lpszConnectString:数据库的连接字符串,一般格式为:DSN=OracleServer_Source;UID=***,PWD=***
4、要从数据库中查询数据,就必须要使用CRecordset类对象,在对数据集进行操作之前要先定义一个CRecordset类对象,并传入CDatabase指针,方法如下:
CRecordset rs(&m_db);或是CRecordset rs;rs.m_pDatabase=&m_db;
5、然后要调用CRecordset的Open方法打开记录集,Open函数的原型如下:
virtual BOOl Open(UINT nOpenType=AFX_DB_USE_DEFAULT_TYPE,LPCTSTR lpszSQL=NULL,DWORD dwOptions=none);throw(CDBException,CMemoryException);
1)nOpenType为记录集的打开方式,包括dynaset,Snapshot,dunamic和forwardOnly
2)lpszSQL可以是要打开记录集的SQL语句,也可以是一个表名或是一个存储过程。
3)dwOptions一般情况下为空
6、添加、修改和删除数据都只需用到CDatabase类的ExecuteSQl方法来执行SQL语句,ExecuteSQL函数的原型如下:
void ExecuitSQL(LPCSTR lpszSQL);throw(CDBException);
1)lpszSQL代表一个SQL语句。
代码实例(昨天研究一天做出的一个小程序中的部分关键代码)
1、建立ODBC数据源
2、我的打开数据源连接的函数OnBtnDbconnect()
void CMemoDBSDlg::OnBtnDbconnect()
{
// TODO: Add your control notification handler code here
//从界面控件中获取信息更新到控件变量中
if(!UpdateData(true))
return;
//检出数据库是否已经连接,如果已经连接则返回
if(m_db.IsOpen())
{
AfxMessageBox("数据库已经连接");
return;
}
//检查数据库配置参数
if(m_strDBSource.IsEmpty()||m_strDBUser.IsEmpty()||m_strDBPassword.IsEmpty())
{
AfxMessageBox("数据库参数不能够为空");
return;
}
//创建连接字符串
CString strConnect;
strConnect.Format("DSN=%s;UID=%s;PWD=%s",m_strDBSource,m_strDBUser,m_strDBPassword);
//打开数据库的连接,并且捕获异常
try
{
m_db.OpenEx(strConnect,CDatabase::noOdbcDialog);
}
catch(CDBException *ex)
{
AfxMessageBox(ex->m_strError
AfxMessageBox(ex->m_strStateNativeOrigin);
}
catch(CMemoryException *pEx)
{
pEx->ReportError();
AfxMessageBox("memory exception");
}
catch(CException *e)
{
TCHAR szError[1000];
e->GetErrorMessage(szError,1000);
AfxMessageBox(szError);
}
InitCtrlData();
}
3、获取数据
//从数据库中读取数据并显示在列表框中
void CMemoDBSDlg::InitCtrlData()
{
try
{
CRecordset rs;
rs.m_pDatabase=&m_db;
//////////////////////////////////
///向成员列表控件中添加成员记录信息
//////////////////////////////////
CString sql="select * from family_member_tab";
rs.Open(CRecordset::dynaset,sql);
MessageBox("查询家庭成员的SQL成功执行");
int id;
CString name,date;
while(!rs.IsEOF())
{
CDBVariant var;
//获取成员ID字段值
rs.GetFieldValue((short)0,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
id=var.m_iVal;
var.Clear();
//获取姓名字段值
rs.GetFieldValue(1,name);
//获取出生日期字段值
rs.GetFieldValue(2,date);
//把记录值插入成员列表控件中
InsertMemberItem(id,name,date.Left(10));
//下一条数据
rs.MoveNext();
}
rs.Close();
//////////////////////////////////
///向备忘录类型控件中添加备忘录信息
//////////////////////////////////
sql="select * from memo_type_tab";
//获取所有备忘录信息记录
rs.Open(CRecordset::dynaset,sql);
MessageBox("查询Memo类型的SQL成功执行");
while(!rs.IsEOF())
{
CDBVariant var;
//获取备忘类型ID字段值
rs.GetFieldValue((short)0,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
id=var.m_iVal;
var.Clear();
//获取类型名字段值
rs.GetFieldValue(1,name);
//把记录值插入成员列表控件中
InsertMemoTypeItem(id,name);
//下一条数据
rs.MoveNext();
}
rs.Close();
////////////////////////////////
///向备注列表中加入所有的备注信息
////////////////////////////////
sql="select * from memo_info_tab";
rs.Open(CRecordset::dynaset,sql);
MessageBox("查询MemoInfo的SQL成功执行");
while(!rs.IsEOF())
{
CDBVariant var;
int memoID,memberID,isEvent,nType;
CString happenDate,operDate,memoTxt,strName,strType;
//获取备忘类型ID字段值
rs.GetFieldValue((short)0,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
memoID=var.m_iVal;
//获取成员字段ID值
rs.GetFieldValue((short)1,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
memberID=var.m_iVal;
//获取操作日期字段
rs.GetFieldValue(2,operDate);
//获取发生日期字段值
rs.GetFieldValue(3,happenDate);
var.Clear();
//获取是否大事记字段值
rs.GetFieldValue(4,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
isEvent=var.m_iVal;
var.Clear();
//获取备忘录类型ID
rs.GetFieldValue(5,var,SQL_C_SLONG);
if(var.m_dwType!=DBVT_NULL)
nType=var.m_iVal;
var.Clear();
//获取备忘录内容字段值
rs.GetFieldValue(6,memoTxt);
CRecordset rs2;
rs2.m_pDatabase=&m_db;
//获取成员ID的姓名