《VC++实现数据库访问.docx》由会员分享,可在线阅读,更多相关《VC++实现数据库访问.docx(12页珍藏版)》请在三一办公上搜索。
1、一、数据库连接1、标准的访问数据库的技术ODBC(Open Database Connectivity,开发数据库互联)ODBC为编写关系数据库的客户软件提供了一种统一的接口 ODBC提供了一个单一的API, 可用于处理不同数据库的客户应用程序。使用ODBC API的应用程序可以与任何具有ODBC 驱动程序的关系数据库进行通信。现在,绝大多数关系数据库都提供了 ODBC驱动程序, 那么我们使用ODBC API就可以访问这些数据库。ODBC的体系结构如下:各神关我们所编写的客户程序直接和ODBC驱动程序管理器打交道,后者利用ODBC驱动程序所 提供的API访问数据库。在访问不同数据库时,需要指定
2、相应的ODBC驱动程序,而后者 又由ODBC程序管理器去调用,它会将客户的请求转换为相应的ODBC驱动,传递给数据 库。DAO(Data Access Object,数据访问对象)DAO就是一组Microsoft Access/Jet数据库引擎的COM自动化接口。DAO不像ODBC那样 是面向C/C+程序员的,它是微软提供给Visual Basic开发人员的一种简单的数据访问方法, 用于操作Access数据库。该技术很少使用,将逐渐退出历史的舞台。RDO(Remote Data Object,远程数据对象)由于RDO直接调用ODBC API(而不是像DAO那样通过Jet引擎),因此,可以为使用
3、关系 数据库的应用程序提供更好的性能。OLE DB(对象链接与嵌入数据库)OLE DB在两个方面对ODBC进行了扩展。首先,OLEDB提供了一个数据库编程的COM 接口;第二,OLEDB提供了一个可用于关系型和非关系型数据源的接口,而ODBC只能访 问关系型数据库。通常我们所说的数据库都是指关系型和非关系型数据源的接口,而ODBC 只能访问关系型数据库。通常我们所说的数据库都是指关系型数据库。但是数据库的概念, 从广义上来说,除了关系型数据库以外,还包括其他格式的数据源,包括电子表格、文本文 件。OLE DB的两个基本结构式OLE DB提供程序和OLE DB用户程序。OLEDB的功能非 常强大
4、,但是它对自动化的支持不是很好。OLE DB的体系结构如下:其它非关 系型存储ADO(AcitveX Data Object, ActiveX 数据对象)ADO建立在OLEDB之上。ADO是一个OLE DB用户程序,即它本身也是一个Consumer。 使用ADO的应用程序都要间接地使用OLE DB。ADO简化了 OLE DB,提供了对自动化的 支持,使得像VBScript这样的脚本语言也能使用ADO访问数据库。采用ADO技术访问数 据库的话,实际上调用过程是ADO客户程序通过ADO再访问OLEDB提供程序,所以访 问速度要慢些。但是因为ADO对自动化提供了很好的支持。该技术很少使用,将逐渐退出
5、 历史的舞台。2、ADO的三个核心对象 Connection 对象:Connection对象表示了到数据库的连接,它管理应用程序和数据库之间的通信。Recordset 和Command对象都有一个ActiveConnection属性,该属性用来引用Connection对象。 Command 对象:Command对象被用来处理重复执行的查询,或处理需要检查在存储过程调用中的输出或返 回参数的值的查询。Recordset 对象:Recordset对象被用来获取数据。Recordset对象存放查询的结果,这些结果由数据的行(称 为记录)和列(称为字段)组成。每一列都存放在Recordset的Fiel
6、ds集合中的一个Field对象中。3、实例讲解,利用ADO访问数据库(1)、新建一个基于对话框的MFC工程Ado。设计ID为IDD_ADO_DIALOG的对话框如下:(2) 、在编译头文件StdAfx.h中导入ADO库:#import C:Program FilesCommon FilesSystemado msado15.dll no_namespace rename (EOF”,”adoEOF”)。同时将Access数据库Test.mdb复制到该工程的目录下。说明:no_namespace表示不需要命名空间,主要是为了访问方便,在程序中可以直接访问 ADO 提供的 Connection、C
7、ommand 和 Recordset 这三个 COM 接口。rename 将 EOF 改为 adoEOF,因为EOF表示记录集的结尾,文件也是以EOF为结尾的,为了避免冲突,在导 入ADO库时,需要将EOF该为adoEOF(该名字由自己定义)。提示:编译该Ado程序,会在该工程目录下的Debug目录下生成msado15.tlh和msado15.tli, 可将msado15.tlh看作是一个头文件,把msado15.tli看作一个源文件。这两个文件是导入 ADO库后,编译器在编译时自动生成的。(3) 、为Query按钮添加单击消息响应函数,利用ADO对象访问数据库:void CAdoDlg:On
8、BtnQuery()CoInitialize(NULL);/初始化 COM 库(CListBox*)GetDlgItem(IDC_LIST1)-ResetContent();/清空编辑框中的数据/_ConnectionPtr是一个智能指针,在msado15.tlh文件中被定义,用该指针定义一个ADO Connection对象,_uuidof获取ADO Connection接口的全局唯一标识符,对pConn对象进行 初始化。_ConnectionPtr pConn(_uuidof(Connection);_RecordsetPtr pRst(_uuidof(Recordset);/产生一个记录集
9、智能指针对象设置连接字符串,不同的数据库使用不同的连接字符串pConn-ConnectionString=Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Test.mdb;pConn-Open(”,”,”,adConnectUnspecified);/上面已经设置了连接字符串,这里所以设 置参数为” adConnectUnspecified表示同步打开连接。pRst=pConn-Execute(select * from Test,NULL,adCmdText);/从 Test表中取出数据,得 到记录集数据while(!pRst-adoEOF)获取Na
10、me字段的数据(CListBox*)GetDlgItem(IDC_LIST1)-AddString(_bstr_t)pRst-GetCollect(Name);pRst-MoveNext();/让游标向下移动pRst-Close();/关闭记录集pConn-Close();/关闭连接pRst.Release();/释放智能指针在相应COM接口的引用计数pConn.Release();/智能指针在访问其他方法和属性时用箭头指向操作符(-),Release方 法释放引用计数时必须使用点操作符(.)。CoUninitialize();/卸载 COM 库(4) 、使用记录集智能指针对象直接指向SQL查
11、询语句获取记录集数据将Query按钮的单击消息响应函数OnBtnQuery中的pRst=pConn-Execute(select * from Test”,NULL,adCmdText);改为pRst-Open(select * from Test”,_variant_t(IDispatch*)pConn), adOpenDynamic,adLockOptimistic,adCmdText);(5) 、使用Command智能指针对象访问数据库void CAdoDlg:OnBtnQuery()CoInitialize(NULL);(CListBox*)GetDlgItem(IDC_LIST1)-
12、ResetContent();_ConnectionPtr pConn(_uuidof(Connection);_RecordsetPtr pRst(_uuidof(Recordset);_CommandPtr pCmd(_uuidof(Command);/亦构造 Command 智能指针对象pConn-ConnectionString=Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Test.mdb”;pConn-Open(”,”,”,adConnectUnspecified);pCmd-put_ActiveConnection(_variant_t
13、(IDispatch*)pConn);/设 置活动连接pCmd-CommandText=select * from Test”;/设置 Command 对象的命令文本属性pRst=pCmd-Execute(NULL,NULL,adCmdText);/执行 Command 对象的 Execute 方法, 将结果赋给记录集对象while(!pRst-adoEOF)(CListBox*)GetDlgItem(IDC_LIST1)-AddString(_bstr_t)pRst-GetCollect(Name);pRst-MoveNext();pRst-Close();pConn-Close();pRs
14、t.Release();pConn.Release();CoUninitialize();二、访问数据库,以ACCESS数据库为例1、创建ACCESS数据库(1) 、打开 Microsoft Office Access,新建 Access 数据库 stu.mdb。(2) 、在stu.mdb中新建一张表stu,在该表中有字符串类型的学号stuNo,字符串类型的姓名 stuName、字符串类型的性别stuSex。其中stuNo是主键。2、利用ODBC访问Access数据库(1) 、新建单文档类型的MFC工程MFCODBCo(2) 、在向导的第二步,选择Database view without f
15、ile support】按钮,再单击Data Source 按钮。弹出【Database Options】对话框,选择【ODBC】单选按钮,然后从下拉列表中选择 MS Access Database,单击【OK】按钮,选择创建的Access数据库stu.mdb,其中表选择stu 表。说明:经过上面步骤,MFC向导自动建立了与ODBC数据源的连接,并将记录集的字段与 相应的变量联起来了,具体在MFCODBCSet.h、MFCODBCSet.cpp文件中添加了代码。(3) 、设计IDD_MFCODBC_FORM对话框如下:该对话框各控件的信息如下:控件控件ID控件属性控件变量StuNo:后的编辑框
16、IDC_EDIT_NO默认CString类型的变量 m_strNoStuName:后的编辑框IDC_EDIT_NAME默认CString类型的变量 m_strNameStuSex:后的编辑框IDC_EDIT_SEX默认CString类型的变量 m_strSexInsert按钮IDC_ADD默认无Delete按钮IDOK_DEL默认无Query按钮IDC_QUERY默认无Quit按钮IDCANCEL默认无列表控件(LList Control)IDC_LISTStyles 选项下,View 选择ReportCListCtrl控件类型的 变量 m_ctrList(4)、为 CMFCODBCView
17、类添加 int 类型的 public 变量 m_iCount 和 CMFCODBCSet*类型的public 变量 m_pSet。(5) 、在程序启动时,需要建立记录集,将记录集中的所有数据读取到列表控件中,即在CMFCODBCView类的 OnInitialUpdate 函数中添加:设置列表风格m_ctrList.SetExtendedStyle(LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES);设置列表的列名称m_ctrList.InsertColumn(0,_T(StuNo),LVCFMT_IMAGE|LVCFMT_LEFT);m_ctrList.Insert
18、Column(1,_T(StuName);m_ctrList.InsertColumn(2,_T(StuSex);获得客户区大小CRect rect;GetClientRect(&rect);设置列表的列宽度m_ctrList.SetColumnWidth(0,rect.Width()/3);m_ctrList.SetColumnWidth(1,rect.Width()/3);m_ctrList.SetColumnWidth(2,rect.Width()/3);OnQuery();/查询并显示所有数据(6) 、为Insert按钮添加消息响应函数,在该函数中完成数据的添加:void CMFCOD
19、BCView:OnAdd() UpdateData();m_pSet-AddNew();/添 加记录m_pSet-m_stuNo=m_strNo;/添加学号m_pSet-m_stuName=m_strName;/添 加姓名m_pSet-m_stuSex=m_strSex;/添加性别m_pSet-Update();/更 新记录m_pSet-Requery();/重 新执行查询m_pSet-MoveLast();/移 动到最后一条记录 OnQuery();说明:m_pSet指向的记录字段可以在MFCODBCSet.h中看到。(7) 、为Delete按钮添加消息响应函数,在该函数中完成数据的删除:v
20、oid CMFCODBCView:OnDel() m_pSet-Delete();/删除最后一条记录m_pSet-Requery();/重 新执行查询OnQuery();/查询并显示所有数据(8) 、为Query按钮添加消息响应函数,在该函数中完成数据的查询:void CMFCODBCView:OnQuery() m_ctrList.DeleteAllItems();/删除列表中的所有记录m_iCount=0;/初始化记录数m_pSet-MoveFirst();/移动到记录集的第一条while(!m_pSet-IsEOF()/判断是否到了记录集的结尾读取记录并将其插入列表中m_ctrList.
21、InsertItem(m_iCount,m_pSet-m_stuNo,0);m_ctrList.SetItemText(m_iCount,1,m_pSet-m_stuName);m_ctrList.SetItemText(m_iCount,2,m_pSet-m_stuSex);m_iCount+;/增加记录序号m_pSet-MoveNext();/移 动到下一条记录m_pSet-MoveLast();/移 动到最后一条记录3、利用ADO访问Access数据库(1) 、新建基于对话框的MFC工程MFCAdo。(2) 、设计对话框 IDD_MFCADO_DIALOG 如下:该对话框各控件的信息如下
22、:控件控件ID控件属性控件变量StuNo:后的编辑框IDC_EDIT_NO默认CString类型的变量 m_strNoStuName:后的编辑框IDC_EDIT_NAME默认CString类型的变量 m_strNameStuSex:后的编辑框IDC_EDIT_SEX默认CString类型的变量 m_strSexInsert按钮IDC_ADD默认无Update按钮IDC_UPDATE默认无Delete按钮IDOK_DEL默认无Query按钮IDC_QUERY默认无Quit按钮IDCANCEL默认无列表控件(List Control)IDC_LISTStyles 选项下,ViewCListCtrl
23、控件类型的选择Report变量 m_ctrList(3) 、导入ADO库,在头文件StdAfx.h中添加:#import C:Program FilesCommon FilesSystemadomsado15.dll no_namespace rename(”EOF”,”adoEOF”)(4) 、初始化 COM 库,在 CMFCAdoApp 类的 InitInstance 函数中添加:CoInitialize(NULL);(5) 、为CMFCAdoDlg类头文件中定义智能指针变量,用于操作数据库:public:_ConnectionPtr m_pConnection;/数 据库连接指针_Rec
24、ordsetPtr m_pRecordset;/数 据库记录集指针(6) 、为CMFCAdoDlg类添加OpenDatabase成员函数用于数据库的连接和表的打开:BOOL CMFCAdoDlg:OpenDatabase(const CString strSQL) _bstr_t strConnect;/连接字符串变量定义strConnect=Provider=Microsoft.Jet.OLEDB.4.0;Data Source=stu.mdb;HRESULT hr;/返回值变量定义连接并打开数据库try创建Connection对象hr=m_pConnection.CreateInstanc
25、e(_uuidof(Connection);if (SUCCEEDED(hr)/若Connection对象创建成功,连接数据库hr=m_pConnection-Open(strConnect,adModeUnknown);catch (_com_error e)/捕获异常CString errormessage;/错误信息变量定义errormessage.Format(Connect database fail!rnerror messageis :%s,e.ErrorMessage();/连接数据库失败,格式化错误信息AfxMessageBox(errormessage);/显示 错误信息
26、return FALSE;/发生异常,返回 /打开表trym_pRecordset.CreateInstance(_uuidof(Recordset);/创建 RecordSet 对象m_pRecordset-CursorType=adOpenStatic;/指定游标类型m_pRecordset-CursorLocation=adUseClient;/指 指定游标位置m_pRecordset-Open(_variant_t)strSQL,_variant_t(IDispatch*)m_pConnection,true),adOp enStatic,adLockOptimistic,adCmdT
27、ext);/打 开表catch(_com_error e)CString errormessage;errormessage.Format(Open database fail!rnerror message is:%s”,e.ErrorMessage();AfxMessageBox(errormessage);return FALSE;return TRUE;(7) 、为CMFCAdoDlg类添加CloseDatabase成员函数,关闭数据库:void CMFCAdoDlg:CloseDatabase() if (m_pConnection-State)/若数据库已经打开,则关闭m_pCon
28、nection-Close();(8) 、在CMFCAdoDlg类的OnInitDialog函数中初始化列表控件并将数据库中的数据显示到 列表控件中:/初始化用户信息列表控件:SendMessage(m_ctrList.m_hWnd,LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT,LVS_EX_FULLROWSELECT);CRect rect;m_ctrList.GetClientRect(&rect);/获得列表控件区域m_ctrList.InsertColumn(0,StuNo”,LVCFMT_LEFT,rect.Width()/3)
29、;添 加学号列m_ctrList.InsertColumn(1,StuName”,LVCFMT_LEFT,rect.Width()/3);m_ctrList.InsertColumn(2,StuSex”,LVCFMT_LEFT,rect.Width()/3);/在列表中显示所有用户信息int iItem=0;CString strSQL=select * from stu;OpenDatabase(strSQL);/连接并打开数据库和表while(!m_pRecordset-adoEOF)读取记录并将数据插入到列表控件中iItem=m_ctrList.InsertItem(0xffff,(_b
30、str_t)(m_pRecordset-GetCollect(StuNo);m_ctrList.SetItem(iItem,1,1,(_bstr_t)(m_pRecordset-GetCollect(StuName),NULL,0,0,0);m_ctrList.SetItem(iItem,2,1,(_bstr_t)(m_pRecordset-GetCollect(StuSex),NULL,0,0,0);m_pRecordset-MoveNext();/移 动记录集指针CloseDatabase。;/关闭数据库(9) 、为Add按钮添加消息响应函数,在该函数中完成数据的添加:void CMFCA
31、doDlg:OnAdd()UpdateData();/将数据写入数据库CString strSQL=select * from stu;OpenDatabase(strSQL);m_pRecordset-AddNew();/添 加一条记录m_pRecordset-PutCollect(StuNo”,(_variant_t)m_strNo);/脯 入学号 m_pRecordset-PutCollect(StuName”,(_variant_t)m_strName);/插 入姓名 m_pRecordset-PutCollect(StuSex,(_variant_t)m_strSex);/插 入性别
32、 m_pRecordset-Update();/更 新数据库CloseDatabase();/关闭数据库int iCurrentSel=0;/定 义行号变量iCurrentSel=m_ctrList.InsertItem(0xffff,);/获得列表行号m_ctrList.SetItemText(iCurrentSel,0,m_strNo);/插 入学号m_ctrList.SetItemText(iCurrentSel,1,m_strName);/插 入姓名m_ctrList.SetItemText(iCurrentSel,2,m_strSex);/插 入性别m_ctrList.SetItem
33、State(iCurrentSel,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);/设置当前行状态m_ctrList.SetHotItem(iCurrentSel);m_ctrList.SetFocus();/设置当前行拥有焦点(10) 、为CMFCAdoDlg类添加int类型的变量m_iCurrentSel,用于获得选中行号。再为列表 控件IDC_LIST添加LVN_ITEMCHANGED消息响应函数,在该函数中获得当前选中的行 号,并将数据载入相应的控件中:void CMFCAdoDlg:OnItemchangedList(N
34、MHDR* pNMHDR, LRESULT* pResult)NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;/ TODO: Add your control notification handler code hereif (pNMListView-uNewState&LVIS_SELECTED)m_iCurrentSel=pNMListView-iItem;/获得选中行号获得列表控件当前选中的一行数据_variant_t vNo,vName,vSex;CString strSQL=select * from stu;OpenDatabase(
35、strSQL);m_pRecordset-Move(m_iCurrentSel,_variant_t(long)adBookmarkFirst);/查 找 指 定 记录vNo=m_pRecordset-GetCollect(stuNo);/获取学号 vName=m_pRecordset-GetCollect(stuName);vSex=m_pRecordset-GetCollect(stuSex);m_strNo=(LPCTSTR)(_bstr_t)vNo;/将学号赋给控件变量 m_strName=(LPCTSTR)(_bstr_t)vName;m_strSex=(LPCTSTR)(_bstr
36、_t)vSex;CloseDatabase();UpdateData(FALSE);*pResult = 0;(11) 、为Update按钮添加消息响应函数,在该函数中完成数据的修改:void CMFCAdoDlg:OnUpdate()UpdateData();CString strSQL=”;strSQL.Format(Update stu set stuNo=%s,stuName=%s,stuSex=%s where stuNo=%s,m_strNo,m_strName,m_strSex,m_strNo);/格式化 SQL 语句OpenDatabase(strSQL);CloseDatab
37、ase();/更新数据到列表控件m_ctrList.SetItemText(m_iCurrentSel,0,m_strNo);/插 入学号m_ctrList.SetItemText(m_iCurrentSel,1,m_strName);m_ctrList.SetItemText(m_iCurrentSel,2,m_strSex);m_ctrList.SetItemState(m_iCurrentSel,LVIS_SELECTED|LVIS_FOCUSED,LVIS_SELECTED|LVIS_FOCUSED);m_ctrList.SetHotItem(m_iCurrentSel);m_ctrL
38、ist.SetFocus();(12) 、为Delete按钮添加消息响应函数,在该函数中完成数据的删除:void CMFCAdoDlg:OnDel() CString strSQL=”;strSQL.Format(delete from stu where stuNo=%s,m_strNo);/格式化 SQL 更新语句OpenDatabase(strSQL);CloseDatabase();m_ctrList.DeleteItem(m_iCurrentSel);/删除选中行(13) 、为Query按钮添加消息响应函数,在该函数中完成数据的查询:void CMFCAdoDlg:OnQuery()
39、 UpdateData();/更 新数据CString strSQL=;/SQL 语句CString strWhere=;/查询条件if (!m_strNo.IsEmpty()/若学号不为空,则添加学号条件strWhere=stuNo=+m_strNo+;if (!m_strName.IsEmpty()/若姓名不为空,添加姓名条件if (!strWhere.IsEmpty()strWhere=strWhere+and stuName=+m_strName+;elsestrWhere=stuName=+m_strName+;if (!m_strSex.IsEmpty()/性别不为空,添加性别条件
40、if (!strWhere.IsEmpty()strWhere=strWhere+and stuSex=+m_strSex+;elsestrWhere=stuSex=+m_strSex+;strSQL=select * from stu where +strWhere;OpenDatabase(strSQL);m_ctrList.DeleteAllItems();/清空列表控件中的数据int iItem=0;while (!m_pRecordset-adoEOF)读取记录并将数据添加到列表控件中iItem=m_ctrList.InsertItem(0xffff,(_bstr_t)(m_pRecordset-GetCollect(stuNo);m_ctrList.SetItem(iItem,1,1,(_bstr_t)(m_pRecordset-GetCollect(stuName),NULL,0,0,0);m_ctrList.SetItem(iItem,2,1,(_bstr_t)(m_pRecordset-GetCollect(stuSex),NULL,0,0,0);m_pRecordset-MoveNext();CloseDatabase();/关闭数据库