背景对于数据库的操作使用,对于我们编程开发来说,是比较常见的事情,也是常用的技术。所以,应该要熟悉掌握。对于数据库的操作,基本操作就是增、删、改、查。但是,在进行这些基本操作之前,还有至关重要的一步,就是数据库的连接。对于数据库的成功连接,那么,我们对数据库的操作就完成一半了。很多初学者,都会卡死在数据库连接这一步上面。
本文介绍的是ADO方式连接数据库,并操作数据库。ADO(ActiveX Data Object)具有跨系统平台特性,它直接对DBMS数据库进行操作,即系统中必须有DBMS,但不需要驱动程序,不需要注册数据源,所以具有很好的可移植性。
本文就给出ADO方式连接并操作 SQL Server数据、Access数据库、Oracle数据库、MySQL数据库等常用数据库,虽然有很多数据库,但是它们之间对于ADO来说,只是连接字符串的区别而已。
现在,我就把程序实现的过程整理成文档,分享给大家。
实现原理ADO对象的导入在使用ADO技术时需要导入一个ADO动态链接库msado15.dll,该动态库位于系统盘下的”Program Files\Common Files\System\ado\”目录下。然后,我们在程序头文件中,添加下面的导入代码:
#import "C:\\Program Files\\common files\\system\\ado\\msado15.dll" no_namespace rename("EOF","adoEOF")
数据库连接我们在操作数据库之前,首先要连接数据库。数据库连接至关重要一点就是,数据库连接字符串。现在,我们先来介绍下ADO连接数据库的一个流程:
首先,我们先调用 CoInitialize 初始化COM组件环境,因为ADO方式连接数据库,就是基于COM组件实现的。所以,必须要对COM环境进行初始化
然后,调用 _ConnectionPtr::CreateInstance 函数创建 Connection 对象
创建成功后,对 Connection 对象的连接超时ConnectionTimeout进行设置,同时调用 Open 函数,按照数据库连接字符串连接数据库
经过,这 3 步操作,就成功完成数据库连接的操作。我们上面说,不同数据库,连接字符串也会不同。下面,我就列举常用数据库的连接字符串:
Access连接字符串
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=MDB文件路径;Persist Security Info=False;Jet OLEDB:DataBase Password=数据库密码
数据源连接字符串
"DSN=TestDatabase;UID=;PWD=;"
SQL Server连接字符串
Driver=SQL Server;Server=服务器IP;Database=数据库名称;UID=用户名;PWD=密码
Oracle连接字符串
Provider=MSDAORA.1; Password=sa123; User ID=system; Data Source=192.168.0.221/orcl; Persist Security Info=True
MySQL连接字符串
Driver=MySQL ODBC 5.2 ANSI Driver;SERVER=192.168.0.221;UID=用户名;PWD=密码;DATABASE=test;PORT=端口(默认填写3306)
// 以ADO方式连接数据库BOOL ADOConnectDatabase(_bstr_t ConnectionString, _bstr_t UserID, _bstr_t Password){ // 初始化COM对象 ::CoInitialize(NULL); try { // 创建Connection对象 HRESULT hr = g_pConnection.CreateInstance("ADODB.Connection"); if (SUCCEEDED(hr)) { // 连接超时时间 5 秒 g_pConnection->ConnectionTimeout = 5; // 连接数据库 g_pConnection->Open(ConnectionString, UserID, Password, adModeUnknown); return TRUE; } } catch (_com_error e) { ::MessageBox(NULL, e.Description(), e.ErrorMessage(), MB_OK); } return FALSE;}
执行非查询操作的SQL语句
首先,我们调用 _ConnectionPtr::BeginTrans 函数,开始事务
然后,调用 _ConnectionPtr::Execute 函数执行SQL语句,这里可以提交多条SQL语句。在调用 Execute 函数的时候,数据库还没有执行SQL语句,此时SQL语句还没有生效
最后,我们调用 _ConnectionPtr::CommitTrans 函数提交事务,这时所提交的SQL语句开始按提交顺序执行。如果出错,则调用 _ConnectionPtr::RollbackTrans 函数回滚并结束事务
// 执行操作SQL语句BOOL ExecuteSQL(char *pszSQL){ _variant_t ra; // 开始事务 g_pConnection->BeginTrans(); try { // 执行SQL语句 g_pConnection->Execute((_bstr_t)pszSQL, &ra, adCmdText); // 提交事务 g_pConnection->CommitTrans(); return TRUE; } catch (_com_error e) { ::MessageBox(NULL, e.Description(), e.ErrorMessage(), MB_OK); } // 如果出现错误,回滚并结束事务 g_pConnection->RollbackTrans(); return FALSE;}
执行查询操作的SQL语句查询SQL语句与其它操作的SQL语句不一样,它不是使用 _ConnectionPtr 对象进程操作的,而是使用记录集对象 _RecordsetPtr 来进行实现。
首先,我们调用 _RecordsetPtr::CreateInstance 函数创建并初始化记录集对象
然后,_RecordsetPtr::Open 函数打开记录集并执行查询SQL语句,将查询结果,返回到记录集中
// 执行查询SQL语句BOOL SearchSQL(char *pszSQL){ // 初始化记录集对象 g_pRecordset.CreateInstance(_uuidof(Recordset)); // 打开记录集 g_pRecordset->Open((LPCTSTR)pszSQL, g_pConnection.GetInterfacePtr(), adOpenDynamic, adLockOptimistic, adCmdText); if (NULL == g_pRecordset) { ::MessageBox(NULL, "读取数据库记录出错", "ERROR", MB_OK); return FALSE; } return TRUE;}
程序测试我们在 main 函数中调用上述封装好的函数,连接数据库,执行创建demongan数据库表的SQL语句,执行向demongan表插入5条数据的SQL语句,执行查询demongan表所有数据并显示在程序上。main 函数为:
int _tmain(int argc, _TCHAR* argv[]){ BOOL bRet = FALSE; char szSQL[MAX_PATH] = {0}; // 连接数据库 bRet = ADOConnectDatabase("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb", "", ""); if (FALSE == bRet) { printf("Connect Database Error.\n"); } printf("Connect Database OK.\n"); // 执行SQL语句,创建表 demongan ::wsprintf(szSQL, "CREATE TABLE demongan(ID int, Name varchar(20), Age int)"); bRet = ExecuteSQL(szSQL); if (FALSE == bRet) { printf("Create Table Error.\n"); } printf("Create Table OK.\n"); // 执行SQL语句,插入 5 条记录 for (int i = 0; i < 5; i++) { ::wsprintf(szSQL, "INSERT INTO demongan(ID, Name, Age) VALUES(%d, \'%s%d\', %d)", i, "Name", i, i + 1); bRet = ExecuteSQL(szSQL); if (FALSE == bRet) { printf("Insert Value Error.\n"); } } printf("Insert Value OK.\n"); // 查询数据 ::wsprintf(szSQL, "SELECT * FROM demongan"); bRet = SearchSQL(szSQL); if (FALSE == bRet) { printf("Search Value Error.\n"); } printf("Search Value OK.\n"); // 从记录集中获取数据并显示 _variant_t varID, varName, varAge; while (!g_pRecordset->adoEOF) { // 获取每个字段对应的数据 varID = g_pRecordset->GetCollect("ID"); varName = g_pRecordset->GetCollect("Name"); varAge = g_pRecordset->GetCollect("Age"); // 注意要强制转换下显示类型 printf("%s\t%s\t%s\n", (LPCTSTR)_bstr_t(varID), (LPCTSTR)_bstr_t(varName), (LPCTSTR)_bstr_t(varAge)); // 获取下一行数据 g_pRecordset->MoveNext(); } system("pause"); return 0;}
我们直接运行程序,程序提示运行成功,成功连接数据库、创建表、插入数据、查询数据并显示查询结果:
我们打开数据库文件,直接查看,数据成功被插入:
总结数据库操作要注意 3 个关键点:
一是与数据库的连接,要注意连接字符串一定要写正确,不同类型的数据库,连接字符串也会不同
二是执行数据库的增加、删除、修改等除查询操作之外的SQL语句,先要开始事务,待所有SQL语句提交完毕后,再一次提交事务,交由数据库操作
三是执行数据库的查询语句,查询结果,需要从记录集中一条一条循环获取,要注意循环结束的条件
其中,在显示从数据集获取的数据的时候,我们要对数据进行(LPCTSTR)强制转化你,例如 (LPCTSTR)_bstr_t(varName),否则数据不能正常显示。
参考参考自《Windows黑客编程技术详解》一书
1
留言
2018-12-31 09:59:50