收藏 分销(赏)

重要VC++使用ADO开发ACCESS数据库.doc

上传人:xrp****65 文档编号:7671136 上传时间:2025-01-11 格式:DOC 页数:26 大小:283KB 下载积分:10 金币
下载 相关 举报
重要VC++使用ADO开发ACCESS数据库.doc_第1页
第1页 / 共26页
重要VC++使用ADO开发ACCESS数据库.doc_第2页
第2页 / 共26页


点击查看更多>>
资源描述
VC++使用ADO开发ACCESS数据库 作者:韩耀旭 本文通过实例演示如何在VC++中使用ADO进行ACCESS数据库编程,并对涉及到的几个概念进行详细解释。 本文不对ADO和ACCESS的基本概念进行详细解释,主要包括以下内容: 第一部分 ADO和ADOX到底是什么,二者的作用和区别建立数据库 第二部分 ADOX创建ACCESS数据库 第三部分 ADO创建ACCESS数据库的表 第四部分 使用_ConnectionPtr接口开发ACCESS数据库 第五部分 使用_RecordsetPtr接口开发ACCESS数据库 第一部分 ADO和ADOX到底是什么,二者的作用和区别 ADO是Microsoft 最新推出的数据库访问的高层软件接口。它和Microsoft以前的数据库访问接口DAO、RDO相比具有更大的灵活性,使用也更方便,开发效率大为提高。 ADOX是核心ADO对象的扩展库。它提供的附加对象可用于创建、修改和删除模式对象,如表和过程。要使用ADOX,则应建立对ADOX类型库的引用。ADOX库文件名为 Msadox.dll。 通俗地讲,ADO是访问数据库的一种接口,可以使用它方便地进行数据库编程。而ADOX是微软对ADO功能的扩展,比如:可以ADOX创建数据库(而ADO没有创建数据库的功能)。 第二部分 ADOX创建ACCESS数据库 用ADOX创建access数据库方法很简单,只需要创建一个Catalog对象,然后调用它的Create方法就可以了。 例程ADOXCreateDatabase演示如何使用ADOX创建一个ACCESS数据库。 打开VC++ 6.0,新建一个基于对话框的工程ADOXCreateDatabase。在对话框IDD_ADOXCREATEDATABASE_DIALOG中添加一个编辑框IDC_DBNAME和一个按钮IDC_BTN_CREATE,编辑框用以输入数据库名称。 使用ClassWizard给编辑框创建一个CString变量m_dbName。 双击IDC_BTN_CREATE按钮,并编辑OnBtnCreate()函数如下: void CADOXCreateDatabaseDlg::OnBtnCreate() { //使输入到编辑框IDC_DBNAME的内容更新到m_dbName变量中 UpdateData(TRUE); CString str; str="d:\\"+m_dbName+".mdb"; //检查该数据库是否已经存在,如果该数据库已经存在,弹出消息框,返回 //使用API函数PathFileExists()检查路径文件是否存在 //请注意:为了使用API函数PathFileExists(),需要加入 //#include "Shlwapi.h" //#pragma comment(lib,"shlwapi.lib") if(PathFileExists(str)) { CString strTemp; strTemp.Format("%s已存在!",str); AfxMessageBox(strTemp); return ; } //定义ADOX对象指针并初始化为NULL //用ADOX创建access数据库方法很简单, //只需要新建一个Catalog对象,然后调用它的Create方法就可以了。 //Catalog是 ADOX 的一个对象,它包含描述数据源模式目录的集合。 //在这里,您只需知道创建数据库时使用这个对象就可以了。 //注意用try...catch组合捕捉错误 _CatalogPtr m_pCatalog = NULL; CString DBName="Provider=Microsoft.JET.OLEDB.4.0;Data source="; DBName=DBName+str; try { m_pCatalog.CreateInstance(__uuidof(Catalog)); m_pCatalog->Create(_bstr_t((LPCTSTR)DBName)); } catch(_com_error &e) { AfxMessageBox(e.ErrorMessage()); return ; } } 使用ADOX,需要引入ADOX的动态链接库msadox.dll,即在stdafx.h中加入如下语句: #import "C:\Program Files\Common Files\system\ado\msadox.dll" no_namespace rename("EOF","adoEOF") 另外,ADOX属于COM对象,所以要在CADOXCreateDatabaseApp::InitInstance()函数中加入: if(!AfxOleInit()) { AfxMessageBox("OLE初始化出错!"); return FALSE; } 初始化COM。 好了,编译并运行该例程,对于编译过程中弹出的4146号警告不要理会。在编辑框中输入一个数据库名称,点击“创建数据库”按钮,该数据库将在d盘根目录下创建,再次输入该数据库名称并点击“创建数据库”按钮,将弹出警告对话框。 在vc中使用ADO的时候会得到4146号警告信息,我们可以不去理会,也可以通过#pragma warning指令解决,方法为: 将在stdafx.h中加入的语句: #import "C:\Program Files\Common Files\system\ado\msadox.dll" no_namespace rename("EOF","adoEOF") 前后再加一条语句,修改后为: #pragma warning (disable:4146) #import "C:\Program Files\Common Files\system\ado\msadox.dll" no_namespace rename("EOF","adoEOF") #pragma warning (default:4146) 指令#pragma warning (disable:4146) 暂时屏蔽编译时4146警告信息 指令#pragma warning (default:4146) 重置编译器的4146警告到默认状态 第三部分 ADO创建ACCESS数据库的表 我们一般用ADOX创建数据库,然后再用ADO创建数据库的表。 例程CREATE_DB_AND_TABLE演示如何使用ADO创建ACCESS数据库的表。 打开VC++ 6.0,新建一个基于对话框的工程CREATE_DB_AND_TABLE。在对话框IDD_CREATE_DB_AND_TABLE_DIALOG中添加如下控件: 控件名称 ID 用途 编辑框 IDC_DBNAME 输入数据库名称 按钮 IDC_BTN_CREATE 创建数据库 编辑框 IDC_TABLENAME 输入表名 按钮 IDC_BTN_CREATE_TABLE 创建表 使用ClassWizard给两个编辑框创建CString变量: 编辑框 CString变量 编辑框IDC_DBNAME m_dbName 编辑框IDC_TABLENAME m_tableName 双击IDC_BTN_CREATE按钮,并编辑OnBtnCreate()函数如下: void CADOXCreateDatabaseDlg::OnBtnCreate() { UpdateData(TRUE); CString str; str="d:\\"+m_dbName+".mdb"; if(PathFileExists(str)) { CString strTemp; strTemp.Format("%s已存在!",str); AfxMessageBox(strTemp); return ; } _CatalogPtr m_pCatalog = NULL; CString DBName="Provider=Microsoft.JET.OLEDB.4.0;Data source="; DBName=DBName+str; try { m_pCatalog.CreateInstance(__uuidof(Catalog)); m_pCatalog->Create(_bstr_t((LPCTSTR)DBName)); } catch(_com_error &e) { AfxMessageBox(e.ErrorMessage()); return ; } } 以上代码例程ADOXCreateDatabase中已经详细叙述。 双击IDC_BTN_CREATE_TABLE按钮,并编辑OnBtnCreateTable()函数如下: void CCREATE_DB_AND_TABLEDlg::OnBtnCreateTable() { //先判断表名编辑框是否为空 UpdateData(TRUE); if(!m_tableName.IsEmpty()) { ADOX::_CatalogPtr m_pCatalog=NULL; ADOX::_TablePtr m_pTable=NULL; CString str; str="c:\\"+m_dbName+".mdb"; CString DBName="Provider=Microsoft.JET.OLEDB.4.0;Data source="; DBName=DBName+str; //这段代码先检查表是否已经存在,如果表已经存在,不再创建,直接返回。 //其实这段代码不必深入研究,只需知道它的功能,直接拿来使用即可 try { m_pCatalog.CreateInstance(__uuidof(ADOX::Catalog)); m_pCatalog->PutActiveConnection(_bstr_t(DBName)); int tableCount=m_pCatalog->Tables->Count; int i=0; while(i<tableCount) { m_pTable=(ADOX::_TablePtr)m_pCatalog->Tables->GetItem((long)i); CString tableName=(BSTR)m_pTable->Name; if(tableName==m_tableName) { AfxMessageBox("该表已经存在!"); return; } i++; } } catch(_com_error &e) { AfxMessageBox(e.Description()); return; } ADODB::_ConnectionPtr m_pConnection; //创建表 _variant_t RecordsAffected; try { m_pConnection.CreateInstance(__uuidof(ADODB::Connection)); //Open方法的原型: //Open(_bstr_t ConnectionString,_bstr_t UserID,_bstr_t Password,long Options) //ConnectionString为连接字串,UserID是用户名,Password是登陆密码 //Options是连接选项,可以是如下几个常量: //adModeUnknown 缺省,当前的许可权未设置 //adModeRead 只读 //adModeWrite 只写 //adModeReadWrite 可以读写 //adModeShareDenyRead 阻止其它Connection对象以读权限打开连接 //adModeShareDenyWrite 阻止其它Connection对象以写权限打开连接 //adModeShareExclusive 阻止其它Connection对象打开连接 //adModeShareDenyNone 阻止其它程序或对象以任何权限建立连接 m_pConnection->Open(_bstr_t(DBName),"","",ADODB::adModeUnknown); } catch(_com_error e) { CString errormessage; errormessage.Format("连接数据库失败!\r错误信息:%s",e.ErrorMessage()); AfxMessageBox(errormessage); return; } try { CString strCommand; /* 执行SQL命令:CREATE TABLE创建表格 该表包含三个字段:记录编号 INTEGER,姓名 TEXT,出生年月 DATETIME SQL语言中的create table语句被用来建立新的数据库表格。 create table语句的使用格式如下: create tablename (column1 data type,column2 data type,column3 data type); 如果用户希望在建立新表格时规定列的限制条件,可以使用可选的条件选项 create table tablename (column1 data type[constraint], column2 data type[constraint], column3 data type[constraint]); 举例: create table employee (firstname varchar(15), lastname varchar(20), age number(3), address varchar(30), city varchar(20)); 简单来说,创建新表格时,在关键词create table后面加入所要建立的表格的名称, 然后在括号内顺次设定各列的名称,数据类型,以及可选的限定条件等。 使用SQL语句创建的数据库表格和表格中列的名称必须以字母开头, 后面可以使用字母,数字或下划线,名称的长度不能超过30个字符, 注意,用户在选择表格名称时不要使用SQL语言中的保留关键字, 如select,create,insert等,作为表格或列的名称 */ strCommand.Format("CREATE TABLE %s(记录编号 INTEGER,姓名 TEXT,出生年月 DATETIME)",m_tableName); //Execute(_bstr_t CommandText,VARIANT* RecordsAffected,long Options) //其中CommandText是命令字串,通常是SQL命令, //参数RecordsAffected是操作完成后所影响的行数 //参数Options表示CommandText中内容的类型,可以取下列值之一: //adCmdText 表明CommandText是文本命令 //adCmdTable 表明CommandText是一个表名 //adCmdProc 表明CommandText是一个存储过程 //adCmdUnknown 未知 m_pConnection->Execute(_bstr_t(strCommand),&RecordsAffected,ADODB::adCmdText); if(m_pConnection->State) m_pConnection->Close(); } catch(_com_error &e) { AfxMessageBox(e.Description()); } } } 这段代码先用ADOX的Catalog对象检查表是否已经存在,如果该表已经存在,直接返回;如果还没有该表,使用ADO的Connection对象的Execute函数创建表。 Connection对象的用法:首先定义一个Connection类型的指针,然后调用CreateInstance()来创建一个连接对象的实例,再调用Open函数建立与数据源的连接。最后使用Execute()函数执行SQL语句创建表。 关于调用CreateInstance()来创建连接对象的实例,还需作一点说明。ADO库包含三个基本接口:_ConnectionPtr接口,_RecordsetPtr接口和_CommandPtr接口。其分别对应Connection对象(完成应用程序对数据源的访问连接),Recordset对象(将查询的结果以记录集的方式存储)和Command对象(对已连接的数据源进行命令操作)。 _ConnectionPtr m_pConnection; _RecordsetPtr m_pRecordset; _CommandPtr m_pCommand; 而这三个对象实例的创建,可以使用如下语句: m_pConnection.CreateInstance(__uuidof(Connection)); 或者: m_pConnection.CreateInstance(“ADODB.Connection”); m_pRecordset.CreateInstance(__uuidof(Recordset)); 或者: m_pRecordset.CreateInstance(“ADODB.Recordset”); m_pCommand.CreateInstance(__uuidof(Command)); 或者: m_pCommand.CreateInstance(“ADODB.Command”); 两种方法的作用完全相同,使用哪种方法,完全是您的个人爱好问题。 如例程ADOXCreateDatabase,在BOOL CCREATE_DB_AND_TABLEApp::InitInstance()函数中加入: if(!AfxOleInit()) { AfxMessageBox("OLE初始化出错!"); return FALSE; } 在stdafx.h中加入如下语句: #import "C:\Program Files\Common Files\system\ado\msadox.dll" #import "C:\Program Files\Common Files\system\ado\msado15.dll" rename("EOF","adoEOF") 关于这两条语句,需要进行特别说明: 由于该例程同时使用ADOX和ADO,需要同时引入msado15.dll和msadox.dll两个库。这两个库的名字空间是不同的,msado15.dll的名字空间是ADODB,msadox.dll的名字空间是ADOX。在使用ADO所属的名字空间的变量,函数时,在前面加上ADODB::,在使用ADOX所属的名字空间的变量,函数时,在前面加上ADOX::。 另外,一般ADOX和ADO分开操作。您也可以在ADOX操作部分使用using namespace ADOX::,而在ADO操作部分使用using namespace ADO:,以区分名字空间。这样,您就不必再使用ADOX::和ADODB::了。 rename(“EOF”,”adoEOF”) //重命名EOF是必要的,因为典型的VC应用都已经定义了EOF作为常数-1,为了避免冲突,将ADO中的EOF重命名为adoEOF。 #import中有一个属性为no_namespace,这是告诉编译器该类不在一个单独的名字空间中,使用no_namespace意味着你不需要在初始化变量的时候引用名字空间。当然如果在您的应用中需要导入多个类型库的话,不要使用no_namespace,以免引起名字冲突。 再通俗一点讲,就是只导入一个类型库的话,可以在#import语句中加入no_namespace属性,您的程序可以直接使用这个类型库的名字空间的内容,而不必使用using namespace XXX;或XXX::,这是因为no_namespace属性告诉编译器该类型库不再名字空间,而是在全局空间上工作;如果您导入几个类型库,而这几个类型库之间没有定义冲突,您也可以在使用no_namespace属性;但如果两个类型库中有定义冲突,就不能使用no_namespace属性,如果使用no_namespace属性,就会在全局空间产生定义冲突。 对于本例程,您可以把stdafx.h中的 #import "C:\Program Files\Common Files\system\ado\msadox.dll" #import "C:\Program Files\Common Files\system\ado\msado15.dll" rename("EOF","adoEOF") 改为 #import "C:\Program Files\Common Files\system\ado\msadox.dll" #import "C:\Program Files\Common Files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF") 这样改动后,void CCREATE_DB_AND_TABLEDlg::OnBtnCreateTable()中的ADODB::需要完全省略掉。 当然,您也可以把这两行改为: #import "C:\Program Files\Common Files\system\ado\msadox.dll" no_namespace #import "C:\Program Files\Common Files\system\ado\msado15.dll" rename("EOF","adoEOF") 但这样改动后,void CCREATE_DB_AND_TABLEDlg::OnBtnCreateTable()中的ADOX::需要完全省略掉。 由于ADOX和ADO有定义冲突,也就是说,msado15.dll和msadox.dll有相同的定义部分,所以在一个程序中,不允许同时使用no_namespace。 第四部分 使用_ConnectionPtr接口开发ACCESS数据库 ADO中最重要的对象有三个:Connection、Recordset和Command,分别表示连接对象、记录集对象和命令对象。三个对象对应的智能指针分别是:_ConnectionPtr、_RecordsetPtr、_CommandPtr。ADO使用_ConnectionPtr这个指针来操纵Connection对象,类似地,后面用到的_CommandPtr和_RecordsetPtr分别表示命令对象指针和记录集对象指针。 Connection对象是这三个对象的基础,它的主要作用是建立与数据库的连接,建立了与数据库的连接后,才能进行其它有关数据库的访问和操作。 也就是说,使用ADO操作数据库,通常先用Connection对象的Open方法打开一个库连接,然后才能进行数据库的操作。操作完成后,要关闭这个库连接。 本文只讲述Connection对象最常用的Open方法和Execute方法。Open方法用于打开一个库连接,而Execute方法一般用于执行一条SQL语句。 _ConnectionPtr智能指针的用法: 首先定义一个Connection类型的指针,然后调用CreateInstance()来创建一个连接对象的实例,再调用Open函数建立与数据源的连接。在建立连接对象后,可以使用连接对象的Execute()函数来执行SQL命令。 _ConnectionPtr智能指针Open方法的原型: Open(_bstr_t ConnectionString,_bstr_t UserID,_bstr_t Password,long Options) ConnectionString为连接字串,UserID是用户名,Password是登陆密码 Options是连接选项,可以是如下几个常量: adModeUnknown 缺省,当前的许可权未设置 adModeRead 只读 adModeWrite 只写 adModeReadWrite 可以读写 adModeShareDenyRead 阻止其它Connection对象以读权限打开连接 adModeShareDenyWrite 阻止其它Connection对象以写权限打开连接 adModeShareExclusive 阻止其它Connection对象打开连接 adModeShareDenyNone 阻止其它程序或对象以任何权限建立连接 _ConnectionPtr智能指针Execute方法的原型: _RecordsetPtr Connection15::Execute(_bstr_t CommandText,VARIANT* RecordsAffected,long Options) 其中CommandText是命令字串,通常是SQL命令, 参数RecordsAffected是操作完成后所影响的行数 参数Options表示CommandText中内容的类型,可以取下列值之一: adCmdText 表明CommandText是文本命令 adCmdTable 表明CommandText是一个表名 adCmdProc 表明CommandText是一个存储过程 adCmdUnknown 未知 Execute执行完后返回一个指向记录集的指针。 例程CREATE_DB_AND_TABLE中已经使用了_ConnectionPtr指针的Open方法和Execute方法,在后面的例程我们将进一步详细说明。 我们先讲解几条最常用的SQL语句。 SELECT查询语句 我们希望用各种不同的方法来查看和分析数据,SELECT语句就是我们要使用的语句,用于有选择的从数据库返回我们需要的数据,也就是查询。 最基本的SELECT语句仅有两个部分:要返回的列和这些列源于的表 为了便于讲解演示,我们使用如下Northwind 示例数据库中的 Employees 表 EmployeeID FirstName LastName HireDate City Country 1 Nancy Davolio 1/5/1992 12:00:00 Seattle USA 2 Andrew Fuller 14/8/1992 12:00:00 Tacoma USA 3 Janet Leverling 1/4/1992 12:00:00 Kirkland USA 4 Margaret Peacock 3/5/1993 12:00:00 Redmond USA 5 Steven Buchanan 17/10/1993 12:00:00 London UK 6 Michael Suyama 17/10/1993 12:00:00 London UK 7 Robert King 2/1/1994 12:00:00 London UK 8 Laura Callahan 5/3/1994 12:00:00 Seattle USA 9 Anne Dodsworth 15/11/1994 12:00:00 London UK 如果我们希望检索Employees表中所有客户的所有信息,我们可以使用星号(*)来简单地表示所有列,查询语句如下所示: SELECT * FROM Employees 如果我们只需要特定列,我们应该在逗号分隔的列表中显式指定这些列,如下所示: SELECT EmployeeID, FirstName,LastName,HireDate FROM Employees 结果会显示该表中所有行的指定字段的数据。 显式指定所需字段还允许我们控制字段返回的顺序,如果我们希望LastName显示在FirstName之前,我们可以编写以下语句: SELECT EmployeeID, LastName,FirstName,HireDate FROM Employees WHERE子句 接下来我们要做的是开始限制或筛选从数据库提取的数据。通过向SELECT语句添加WHERE子句,我们可以添加一个(或多个)条件,所选数据必须满足这些条件,这将限制答复查询的行数也就是被提取的行数。 我们可以在上一个查询的基础上,将其限制为City为London的员工 SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE City = 'London' 查询结果如下: EmployeeID FirstName LastName HireDate City 5 Steven Buchanan 17/10/1993 12:00:00 London 6 Michael Suyama 17/10/1993 12:00:00 London 7 Robert King 2/1/1994 12:00:00 London 9 Anne Dodsworth 15/11/1994 12:00:00 London 如果您希望返回相反条件的员工,即返回那些不住在伦敦的员工,您应该编写以下语句: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE City <> 'London' 您也可以使用大于、小于、大于等于、小于等于等运算符。例如,若要获取其雇佣日期等于某个给定日期或大于该日期的员工列表,您可以编写以下语句: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE HireDate >= '1-july-1993' 您可以得到以下结果行: EmployeeID FirstName LastName HireDate City 5 Steven Buchanan 17/10/1993 12:00:00 London 6 Michael Suyama 17/10/1993 12:00:00 London 7 Robert King 2/1/1994 12:00:00 London 8 Laura Callahan 5/3/1994 12:00:00 Seattle 9 Anne Dodsworth 15/11/1994 12:00:00 London 当然,我们可以编写更复杂的条件:在 WHERE 子句中加入多个条件。如果我们希望了解哪些员工是在两个给定日期之间雇佣的,我们可以编写以下语句: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE (HireDate >= '1-june-1992') AND (HireDate <= '15-december-1993') 结果如下: EmployeeID FirstName LastName HireDate City 2 Andrew Fuller 14/8/1992 12:00:00 Tacoma 4 Margaret Peacock 3/5/1993 12:00:00 Redmond 5 Steven Buchanan 17/10/1993 12:00:00 London 6 Michael Suyama 17/10/1993 12:00:00 London SQL 还有一个BETWEEN 运算符,用于检查某个值是否在两个值之间(包括等于两端的值)。这使我们可以将以前的查询重新编写为: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE HireDate BETWEEN '1-june-1992' AND '15-december-1993' 我们也可以使用 NOT 运算符来提取那些不在指定日期之间的行: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE HireDate NOT BETWEEN '1-june-1992' AND '15-december-1993' 如果我们希望检查一个列值是否等于多个值,那该怎么办呢?如果只是两个值,则很容易对每个值进行测试,方法是,使用 OR 运算符将它们连接在一起,则编写的语句如下所示: SELECT EmployeeID, FirstName, LastName, HireDate, City FROM Employees WHERE City = 'London' OR City = 'Seattle' 但是,如果您希望与三个、四
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 教育专区 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2025 宁波自信网络信息技术有限公司  版权所有

客服电话:4009-655-100  投诉/维权电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服