VC常用数据库操作方法_第1页
VC常用数据库操作方法_第2页
VC常用数据库操作方法_第3页
VC常用数据库操作方法_第4页
VC常用数据库操作方法_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

VC中常用数据库操作的实现1 常用的数据库结构体系概述ODBC(Open Database Connectivity,开放式数据库连接),是一种用来在相关或不相关的数据库管理系统(DBMS)中存取数据的标准应用程序接口(API)。Microsoft Developer Studio为大多数标准的数据库格式提供了32位ODBC驱动器。这些标准数据格式包括有:SQL Server、Access、Paradox、dBase、FoxPro、Excel、Oracle以及Microsoft Text。如果用户希望使用其他数据格式,用户需要相应的ODBC驱动器及DBMS。用户使用自己的DBMS数据库管理 功能生成新的数据库模式后,就可以使用ODBC来登录数据源。对用户的应用程序来说,只要安装有驱动程序,就能注册很多不同的数据库。登录数据库的具体操作参见有关ODBC的联机帮助。ADO(ActiveX Data Object, Active 数据对象)是Microsoft为最新和最强大的数据访问范例 OLE DB 而设计的,是一个便于使用的应用程序层接口。ADO 使您能够编写应用程序以通过 OLE.DB 提供者访问和操作数据库服务器中的数据。ADO 最主要的优点是易于使用、速度快、内存支出少和磁盘遗迹小。ADO 在关键的应用方案中使用最少的网络流量,并且在前端和数据源之间使用最少的层数,所有这些都是为了提供轻量、高性能的接口。OLE DB是”组件对象模型”(COM) 接口,是新的数据库低层接口,它封装了ODBC的功能,并以统一的方式访问存储在不同信息源中的数据。OLE DB是Microsoft UDA(Universal Data Access)策略的技术基础。OLE DB 为任何数据源提供了高性能的访问,这些数据源包括关系和非关系数据库、电子邮件和文件系统、文本和图形、自定义业务对象等等。也就是说,OLE DB 并不局限于 ISAM、Jet 甚至关系数据源,它能够处理任何类型的数据,而不考虑它们的格式和存储方法。在实际应用中,这种多样性意味着可以访问驻留在 Excel 电子数据表、文本文件、电子邮件/目录服务甚至邮件服务器,诸如 Microsoft Exchange 中的数据。但是,OLE DB 应用程序编程接口的目的是为各种应用程序提供最佳的功能,它并不符合简单化的要求。您需要的API 应该是一座连接应用程序和 OLE DB 的桥梁,这就是 ActiveX Data Objects (ADO)。2 操作对象MFC提供的ODBC数据库类:VisualC+的MFC基类库定义了几个数据库类。在利用ODBC编程时,经常要使用到CDatabase(数据库类),CRecordSet(记录集类)和CRecordView(可视记录集类)。 其中: CDatabase类对象提供了对数据源的连接,通过它你可以对数据源进行操作。CRecordSet类对象提供了从数据源 中提取出的记录集。CRecordSet对象通常用于两种形式: 动态行集(dynasets)和快照集(snapshots)。动态行集能保 持与其他用户所做的更改保持同步。快照集则是数据的一个静态视图。每一种形式在记录集被打开时都提供一组记录,所不同的是,当你在一个动态行集里滚 动到一条记录时,由其他用户或是你应用程序中的其他记录集对该记录所做的更改会相应地显示出来。CRecordView类对象能以控制的形式 显示数据库记录。这个视图是直接连到一个CRecordSet对象的表视图。ADO模型包括了下列对象:连接(Connection)、命令 (Command)、记录集 (Recordset)、字段 (Field)、参数 (Parameter)、错误 (Error)、属性 (Property)、集合 、事件.它们之间的关系如下图:3 ODBC的数据库操作应用VisualC+的AppWizard可以自动生 成一个ODBC应用程序框架。方法是:打开File菜单的New选 项,选取Projects,填入工程名,选择MFCAppWizard(exe),然后按AppWizard 的提示进行操作。当AppWizard询问是否包含数据库支持 时,如果你想读写数据库,那么选定Database view with file support;而如果你想访问数据库的信息而不想回写所做 的改变,那么选定Database view without file support选项就比较合 适了。选择了数据库支持之后Database Source按钮会激活, 选中它去调用Data Options对话框。在Database Options对话框中会 显示已向ODBC注册的数据库资源,选定你所要操作的数据库,如:Super_ES,单击OK后会出现Select Database Tables对话 框,其中列举了你所选中的数据库中包含的全部表,选择你希望操作的表后,单击OK。在选定了数据库和数据表之后,你可以按照惯例继续进行AppWizard操作。 特别需要指出的是:在生成的应用程序框架View类(如:CSuper_ESView)中包含一个指向CSuper_ESSet 对象的指针m_pSet,该指针由AppWizard建立,目的是在视表单和记录集之间建立联系,使得记录集中的查询结果能够很容易地在视表单上显示出来。有关m_pSet的详细 用法可以参见VisualC+ OnlineBook。程序与数据语言建立联系,使 用CDatebase:OpenEx()或CDatabase:Open()函数来进行初始化。数据库 对象必须在你使用它构造一个记录集对象之前被初始化。下面举例说明在VisualC+环境中ODBC 的编程技巧:1注册ODBC数据源:SQLConfigDataSource(NULL,ODBC_ADD_SYS_DSN,Microsoft Access Driver (*.mdb)0,DSN=TryDB0DBQ=D:Databasetry.mdb0DEFAULTDIR=D:DATABASE00);- 您可以根据您不同的设置需要修改上面的语句,SQLConfigDataSource一般有以下几个许可的参数:ODBC_ADD_DSN: 加入一个新的用户数据源,ODBC_CONFIG_DSN: 修改一个存在的用户数据源,ODBC_REMOVE_DSN: 删除一个存在的用户数据源,ODBC_ADD_SYS_DSN: 增加一个新的系统数据源,ODBC_CONFIG_SYS_DSN: 修改一个存在的系统数据源,ODBC_REMOVE_SYS_DSN: 删除一个存在的系统数据源,ODBC_REMOVE_DEFAULT_DSN: 删除省缺的数据源说明部分。需要注意的是,当我们使用SQLConfigDataSource ODBC API函数时必须声明包含系统的odbcinst.h头文件,所以我们再选择workspace窗口中FileView打开Header Files中try.h,在其中加入#include odbcinst.h,如果不加入这个头文件,系统编译时就会显示undeclared identifier错误,在完成上述步骤后,假如我们立即编译并Link这个项目,会发现出现下面的错误: tryDlg.obj : error LNK2001: unresolvedexternal symbol _SQLConfigDataSource16Debug/try.exe : fatal error LNK1120: 1 unresolved externals这是因为当我们使用SQLConfigDataSource 这个API函数时候必须用到odbccp32.dll,它是Microsoft提供的32位ODBC安装和管理的DLL,如果是16位必须用到odbcinst.dll,odbccp32.dll有一个import library,所以解决的办法就是把这个odbccp32.lib加到我们的项目中,我们可以打开Project系统菜单项,选Add to Project子菜单,在其中选Files项,打开VC安装目录下的vclib目录,文件类型选Library Files(.lib), 选择其中Odbccp32.lib后按OK键,然后重新编译即可通过2查询记录查询记录使用CRecordSet:Open()和 CRecordSet:Requery()成员函数。在使用CRecordSet类对象之前,必须使用 CRecordSet:Open()函数来获得有效的记录集。一旦已经使用过CRecordSet:Open() 函数,再次查询时就可以应用CRecordSet:Requery()函数。在调 用CRecordSet:Open()函数时,如果已经将一个已经打开的CDatabase 对象指针传给CRecordSet类对象的m_pDatabase成员变量,则使 用该数据库对象建立ODBC连接;否则如果m_pDatabase为空指 针,就新建一个CDatabase类对象并使其与缺省的数据源 相连,然后进行CRecordSet类对象的初始化。缺省数据源 由GetDefaultConnect()函数获得。你也可以提供你所需要的SQL 语句,并以它来调用CRecordSet:Open()函数,例如:-Super_ESSet.Open(AFX_DATABASE_USE_DEFAULT,strSQL);-如果没有指定参数,程序则使 用缺省的SQL语句,即对在GetDefaultSQL()函数中指定的SQL语 句进行操作:CString CSuper_ESSet:GetDefaultSQL()return _T(BasicData,MainSize);-对于GetDefaultSQL()函数返回的表名, 对应的缺省操作是SELECT语句,即:-SELECT * FROM BasicData,MainSize-查询过程中也可以利用CRecordSet的 成员变量m_strFilter和m_strSort来执行条件查询和结果排序。m_strFilter 为过滤字符串,存放着SQL语句中WHERE后的条件串;m_strSort 为排序字符串,存放着SQL语句中ORDERBY后的字符串。 如:Super_ESSet.m_strFilter=TYPE=电动机;Super_ESSet.m_strSort=VOLTAGE;Super_ESSet.Requery();对应的SQL语句为:SELECT * FROM BasicData,MainSize WHERE TYPE=电动机ORDER BY VOLTAGE-除了直接赋值给m_strFilter以外,还 可以使用参数化。利用参数化可以更直观,更方便地 完成条件查询任务。使用参数化的步骤如下:-(1)声明参变量:CStringp1;floatp2;-(2)在构造函数中初始化参变量p1=_T();p2=0.0f;m_nParams=2;-(3)将参变量与对应列绑定pFX-SetFieldType(CFieldExchange:param)RFX_Text(pFX,_T(P1),p1);RFX_Single(pFX,_T(P2),p2);-完成以上步骤之后就可以利用 参变量进行条件查询了:m_pSet-m_strFilter=TYPE=?ANDVOLTAGE=?;m_pSet-p1=电动机;m_pSet-p2=60.0;m_pSet-Requery();-参变量的值按绑定的顺序替换 查询字串中的“?”适配符。-如果查询的结果是多条记录的 话,可以用CRecordSet类的函数Move(),MoveNext(),MovePrev(),MoveFirst() 和MoveLast()来移动光标。-3增加记录-增加记录使用AddNew()函数,要求数据库必须是以允许增加的方式打开:m_pSet-AddNew();/在表的末尾增加新记录m_pSet-SetFieldNull(&(m_pSet-m_type),FALSE); m_pSet-m_type=电动机;./输入新的字段值m_pSet-Update();/将新记录存入数据库m_pSet-Requery();/重建记录集-4删除记录-直接使用Delete()函数,并且在调用Delete() 函数之后不需调用Update()函数:m_pSet-Delete();if(!m_pSet-IsEOF()m_pSet-MoveNext();elsem_pSet-MoveLast();-5修改记录-修改记录使用Edit()函数:m_pSet-Edit();/修改当前记录m_pSet-m_type=发电机;/修改当前记录字段值.m_pSet-Update();/将修改结果存入数据库m_pSet-Requery();-6撤消操作-如果用户选择了增加或者修改记录后希望放弃当前操作,可以在调用Update()函数之前调用:-CRecordSet:Move(AFX_MOVE_REFRESH);-来撤消增加或修改模式,并恢复在增加或修改模式之前的当前记录。其中的参数AFX_MOVE_REFRESH 的值为零。-7数据库连接的复用-在CRecordSet类中定义了一个成员变 量m_pDatabase:-CDatabase *m_pDatabase;-它是指向对象数据库类的指针。如果在CRecordSet类对象调用Open()函数之前,将一个已经打开的CDatabase类对象指针传给m_pDatabase,就能共享相同 的CDatabase类对象。如:CDatabase m_db;CRecordSet m_set1,m_set2;m_db.Open(_T(Super_ES);/ 建 立ODBC 连 接m_set1.m_pDatabase=&m_db;/m_set1 复 用m_db 对 象m_set2.m_pDatabse=&m_db;/ m_set2 复 用m_db 对 象-8SQL语句的直接执行-虽然通过CRecordSet类,我们可以完成 大多数的查询操作,而且在CRecordSet:Open()函数中也可以 提供SQL语句,但是有的时候我们还想进行一些其他操 作,例如建立新表,删除表,建立新的字段等等,这 时就需要使用到CDatabase类的直接执行SQL语句的机制。通 过调用CDatabase:ExecuteSQL()函数来完成SQL语句的直接执行:BOOL CDB:ExecuteSQLAndReportFailure(const CString& strSQL)TRYm_pdb-ExecuteSQL(strSQL);/直接执行SQL语句CATCH (CDBException,e)CString strMsg;strMsg.LoadString(IDS_EXECUTE_SQL_FAILED);strMsg+=strSQL;return FALSE;END_CATCH return TRUE;-应当指出的是,由于不同DBMS提 供的数据操作语句不尽相同,直接执行SQL语句可能会 破坏软件的DBMS无关性,因此在应用中应当慎用此类操 作。-9动态连接表-表的动态连接可以利用在调用CRecordSet:Open() 函数时指定SQL语句来实现。同一个记录集对象只能访 问具有相同结构的表,否则查询结果将无法与变量相 对应。void CDB:ChangeTable()if (m_pSet-IsOpen()m_pSet-Close();switch (m_id)case 0:m_pSet-Open(AFX_DB_USE_DEFAULT_TYPE, SELECT * FROM SLOT0);/ 连 接 表SLOT0m_id=1;break;case 1:m_pSet-Open(AFX_DB_USE_DEFAULT_TYPE, SELECT * FROM SLOT1);/ 连 接 表SLOT1m_id=0;break;-10动态连接数据库-由于与数据库的连接是通过CDatabase 类对象来实现的,所以我们可以通过赋与CRecordSet类对 象参数m_pDatabase以连接不同数据库的CDatabase对象指针,就 可以动态连接数据库。void CDB:ChangeConnect()CDatabase* pdb=m_pSet-m_pDatabase;pdb-Close();switch (m_id)case 0:if (!pdb-Open(_T(Super_ES)/连接数据源Super_ESAfxMessageBox( 数据源Super_ES打开失败,- 请检查相应的ODBC连接, MB_OK|MB_ICONWARNING); exit(0);m_id=1;break;case 1:if (!pdb-Open(_T(Motor)/连接数据源MotorAfxMessageBox(数据源Motor打开失败,- 请检查相应的ODBC连接, MB_OK|MB_ICONWARNING); exit(0);m_id=0;break;4 ADO的数据库实现1、引入ADO库文件使用ADO前必须在工程的stdafx.h文件里用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下所示:代码1:用#import引入ADO库文件#import c:program filescommon filessystemadomsado15.dll no_namespaces rename(EOF adoEOF)这行语句声明在工程中使用ADO,但不使用ADO的名字空间,并且为了避免常数冲突,将常数EOF改名为adoEOF。现在不需添加另外的头文件,就可以使用ADO接口了。2、初始化OLE/COM库环境必须注意的是,ADO库是一组COM动态库,这意味应用程序在调用ADO前,必须初始化OLE/COM库环境。在MFC应用程序里,一个比较好的方法是在应用程序主类的InitInstance成员函数里初始化OLE/COM库环境。代码2:初始化OLE/COM库环境BOOL CADOApp:InitInstance()if(!AfxOleInit()AfxMessageBox(“OLE初始化出错!”);return FALSE; 函数AfxOleInit在每次应用程序启动时初始化OLE/COM库环境。同DAO和CDatabase一样,ADO由几个接口组成:_ConnectionPtr,_CommandPtr和_RecordsetPtr.不同于DAO和Cdatabase的是,ADO基于COM的接口,因此,假如你没有接触过COM,你应该在使用ADO前先找有关书籍了解一下COM。3、ADO接口ADO库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。_ConnectionPtr接口返回一个记录集或一个空指针。通常使用它来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。使用_ConnectionPtr接口返回一个记录集不是一个好的使用方法。通常同CDatabase一样,使用它创建一个数据连接,然后使用其它对象执行数据输入输出操作。_CommandPtr接口返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。如果你只执行一次或几次数据访问操作,后者是比较好的选择。但如果你要频繁访问数据库,并要返回很多记录集,那么,你应该使用全局_ConnectionPtr接口创建一个数据连接,然后使用_CommandPtr接口执行存储过程和SQL语句。_RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定,游标控制等。同_CommandPtr接口一样,它不一定要使用一个已经创建的数据连接,可以用一个连接串代替连接指针赋给_RecordsetPtr的connection成员变量,让它自己创建数据连接。如果你要使用多个记录集,最好的方法是同Command对象一样使用已经创建了数据连接的全局_ConnectionPtr接口,然后使用_RecordsetPtr执行存储过程和SQL语句。4、使用_ConnectionPtr接口_ConnectionPtr是一个连接接口,它类似于CDatabase和CDaoDatabase。它们的工作原理相似。首先创建一个_ConnectionPtr接口实例,接着指向并打开一个ODBC数据源或OLE DB数据提供者(Provider)。以下代码和CDaoDatabase分别创建一个基于DSN和非DSN的数据连接。代码3:使用CDaoDatabase(基于DSN)CDaoDatabase MyDb = new CDaoDatabase();MyDb.Open(NULL,FALSE,FALSE,ODBC;DSN=samp;UID=admin;PWD=admin);代码4:使用CDaoDatabase(基于非DSN)CDaoDatabase MyDb = new CDaoDatabase();MyDb.Open(NULL,FALSE,FALSE,ODBC;DRIVER=SQL Server;SERVER=server;DATABASE=samp;UID=admin;PWD=admin);代码5:使用_ConnectionPtr(基于DSN)_ConnectionPtr MyDb;MyDb.CreateInstance(_uuidof(Connection);MyDb-Open(DSN=samp;UID=admin;PWD=admin,-1);代码6:使用_ConnectionPtr (基于非DSN)_ConnectionPtr MyDb;MyDb.CreateInstance(_uuidof(Connection);MyDb-Open(Provider=SQLOLEDB;SERVER=server;DATABASE=samp;UID=admin;PWD=admin,-1);5、使用_RecordsetPtr接口_RecordsetPtr接口的使用方法和CDaoDatabase类似,通过以下代码的比较,你会发现使用_RecordsetPtr接口非常简单(以下代码使用上面已经创建的数据连接):代码7:使用CDaoDatabase执行SQL语句CDaoRecordset MySet = new CDaoRecordset(MyDb);MySet-Open(AFX_DAO_USE_DEFAULT_TYPE,SELECT * FROM t_samp);Now using ADO:代码8:使用_RecordsetPtr执行SQL语句_RecordsetPtr MySet;MySet.CreateInstance(_uuidof(Recordset);MySet-Open(SELECT * FROM some_table,MyDb.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);现在我们已经有了一个数据连接和一个记录集,接下来就可以使用数据了。从以下代码可以看到,使用ADO的_RecordsetPtr接口,就不需要象DAO那样频繁地使用大而复杂的数据结构VARIANT,并强制转换各种数据类型了,这也是ADO的优点之一。假定程序有一个名称为m_List的的ListBox控件,下面代码我们用_RecordsetPtr接口获取记录集数据并填充这个ListBox控件:代码9:使用DAO访问数据VARIANT * vFieldValue;COleVariant covFieldValue;CString Holder;while(!MySet-IsEOF()MySet-GetFieldValue(FIELD_1, covFieldValue);vFieldValue = (LPVARIANT)covFieldValue;if(vFieldValue-vt!-VT_NULL)Holder.Format(%s,vFieldValue-pbVal);m_List.AddString(Holder);MySet.MoveNext();代码10:使用ADO访问数据_variant_t Holdertrywhile(!MySet-adoEOF)Holder = MySet-GetCollect(FIELD_1);if(Holder.vt!=VT_NULL)m_List.AddString(char*)_bstr_t(Holder);MySet-MoveNext();catch(_com_error * e)CString Error = e-ErrorMessage();AfxMessageBox(e-ErrorMessage();catch(.)MessageBox(ADO发生错误!);必须始终在代码中用try和catch来捕获ADO错误,否则ADO错误会使你的应用程序崩溃。当ADO发生运行时错误时(如数据库不存在),OLE DB数据提供者将自动创建一个_com_error对象,并将有关错误信息填充到这个对象的成员变量.6、使用_CommandPtr接口_CommandPtr接口返回一个Recordset对象,并且提供了更多的记录集控制功能,以下代码示例了使用_CommandPtr接口的方法:代码11:使用_CommandPtr接口获取数据_CommandPtr pCommand;_RecordsetPtr MySet;pCommand.CreateInstance(_uuidof(Command);pCommand-ActiveConnection=MyDb;pCommand-CommandText=select * from some_table;pCommand-CommandType=adCmdText; pCommand-Parameters-Refresh();MySet=pCommand-Execute(NULL,NULL,adCmdUnknown);_variant_t TheValue = MySet-GetCollect(FIELD_1);CString sValue=(char*)_bstr_t(TheValue);7、关于数据类型转换由于COM对象是跨平台的,它使用了一种通用的方法来处理各种类型的数据,因此CString 类和COM对象是不兼容的,我们需要一组API来转换COM对象和C+类型的数据。_vatiant_t和_bstr_t就是这样两种对象。它们提供了通用的方法转换COM对象和C+类型的数据。8、OLE DB连接字符串(SQL Server)Stand

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论