有待补充
ADO全称 ActiveX Data Object.
ActiveX是基于Com技术的。
以下图说明:
ADO是微软高度封装的一个基于OLE DB/ODBC 访问各种关系型数据库/非关系型数据库./其他类型文件等。
ADO通过已有的ODBC程序访问各种数据库,理论上只要数据库开发商有提供ODBC驱动程序就可以被ADO进行I/O操作。
最近学习如何使用ADO 访问Oracle的知识,做个学习笔记。方便以后再次参考
1 ADO库的引入:
ADO库以msado*.dll 命名,以下我已Win7 距离,其他系统暂不了解是否相同.
ADO库所在目录是 : C:\Program Files\Common Files\System\ado\ ,WIN7 ADO库名是: msado15.dll
引入使用 #import 关键字, 在使用的地方或stdafx.h 中包含。
#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF","adoEOF") // 引入时声明没有命名空间,并重命名eof避免编译时引发的报错
2 COM初始化:
ado是基于com技术的,所以在使用之前要初始化com库, 需要头文件 <comdef.h>
有两种情况的初始化:
2.1 MFC
在MFC环境下初始化可以使用函数 AfxOleInit()
2.2 WIN32
在非MFC环境下可以使用 CoInitialize()/UnCoInitialize() 进行【初始化/卸载】com环境
3 ADO 有3个智能指针:
1 _ConnectionPtr //指针一般用于连接数据库,也可以用于数据查询,该指针可以进行事务操作【BeginTrans,CommitTrans,RollbackTrans】
2 _CommandPtr //指针用于执行数据库操作【CRUD】,对于有结果集的可以用_RecordsetPtr 指针对象接收结果集
3 _RecordsetPtr //指针指向一个结果集,可以对结果集进行各种操作。
Mcrosoft 对于数据库的连接不强制要求某个指针是专用,事实上以上三个指针都支持直接发起对数据库的连接及操作。并不需要提前连接到数据库
PS:所有的数据库操作都基于以上三个指针。
指针对象的初始化:
1 //用到两个函数 FAILED / SUCCEEDED 用于判断返回值 2 3 HRESULT hr; 4 //创建实例的两种方式: 5 // #1 6 _ConnectionPtr m_Connection; 7 _CommandPtr m_Command; 8 _RecordsetPtr m_Recordset; 9 10 hr = m_Connection.CreateInstance(__uuidof(Connection)); 11 if(FAILED(hr)) 12 return false; 13 14 hr = m_Command.CreateInstance(__uuidof(Command)); 15 if(FAILED(hr)) 16 return false; 17 18 hr = m_Recordset.CreateInstance(__uuidof(Recordset)); 19 if(FAILED(hr)) 20 return false; 21 22 // #2 23 _ConnectionPtr m_Connection(__uuidof(Connection)); 24 _CommandPtr m_Command(__uuidof(Command)); 25 _RecordsetPtr m_Recordset(__uuidof(Recordset)); 26 27 hr = m_Connection.CreateInstance(__uuidof(Connection)); 28 if(FAILED(hr)) 29 return false; 30 31 hr = m_Command.CreateInstance(__uuidof(Command)); 32 if(FAILED(hr)) 33 return false; 34 35 hr = m_Recordset.CreateInstance(__uuidof(Recordset)); 36 if(FAILED(hr)) 37 return false;
4 连接数据库
智能指针初始化后,可以进行连接到数据库的操作
hr = m_Connection.Open("数据源","用户名","密码",flag); /* 数据源可以使用DSN ,也可以使用not dsn方式。 这里使用非DSN的方式: 指定连接串的格式: "Provider=OraOLEDB.Oracle.1;Data Source=数据库所在主机的全局服务名;" Provider 指定数据库的类型 后面2个参数一个是指向连接数据库的用户名,一个是指向连接数据库的密码, 参数4 是连接的标志位,默认可以-1,或者 adModeUnknow. 已未知的方式打开 */ hr = m_conn->Open("Provider=OraOLEDB.Oracle.1;Data Source=mes;","xxxxx","xxxxx",adModeUnknown); if(FAILED(hr)) return FALSE;
5 关闭数据库连接
1 if(m_Connection->state) 2 m_Connection->Close(); 3 m_Connection = NULL;
6 数据库查询
m_Command->ActiveConnection = m_Connection; // 将已建立的连接直接赋予command对象,避免重复连接。 m_Command->CommandText = "select * from tableName"; //指定查询的sql m_Command->CommandType = adCmdText; // 指定命令类型 adCmdText 指定是文本命令 adCmdTable 指定是一个表明 adCmdProc 指定是一个存储过程 m_Recordset = m_Command->Execute(NULL,NULL,adCmdText); // 执行sql,如果有结果集返回 m_Recordset 接收。 //遍历结果集 _variant_t val; while(m_Recordset ->adoEOF) { //取结果集字段值的两种方式: // 1 val = m_Recordset->GetCollet("name");
val = m_Recordset->GetCollet(long(index)); //以下标的方式访问 // 2 val = m_Recordset->get_Collect("name");
val = m_Recordset->get_Collect(long(index)); printf("%s \n",(LPCSTR)val); //ADO的类型和C++基本类型不相同,需要转换 m_Recordset ->MoveNext(); //移动到下一行记录 }
添加
m_Recordset->AddNew(); //调用 AddNew 增加一行新数据 m_Recordset->PutCollect(); // 调用 PutCollect 给每一个字段赋予数据 PutCollect->Update(); // 确定提交数据
删除
1 m_Recordset->MoveFirst(); //移动到第一条记录 2 m_Recordset->Move(index); //移动到指定的位置 3 4 m_Recordset->Delete(adAffectCurrent); //删除当前记录 5 6 m_Recordset->Update(); //提交操作
调用存储过程:
1 m_Command->ActiveConnection = m_Connection; 2 m_Command->CommandText = "Proc1"; 3 m_Command->Execute(NULL,NULL,adCmdStoredProc);
遍历所有表名:
1 _RecordsetPtr pset = m_Connection->OpenSchema(adSchemaTables); 2 3 while(pset0->adoEOF) 4 { 5 _bstr_t strTblNname = pset->Fields->GetItem("TABLE_NAME")->Value; 6 _bstr_t strTblType = pset->Fields->GetItem("TABLE_TYPE")->Value; 7 8 pset->MoveNext(); 9 } 10 11 pset->Close();
附录:
1、_variant_t (1)、一般传给这3个指针的值都不是MFC直接支持的数据类型,而要用 _variant_t 转换一下
_variant_t(XX) 可以把大多数类型的变量转换成适合的类型传入
(2) 、 _variant_t var;
_variant_t -> long: (long)var;
_variant_t -> CString: CString strValue = (LPCSTR)_bstr_t(var);
CString -> _variant_t: _variant_t( strSql);
2 、 BSTR 宽字符串与 CString 相互转换
BSTR bstr;
CString strSql;
CString -> BSTR: bstr = strSql.AllocSysString();
BSTR -> CString: strSql = (LPCSTR)bstr;
3 、 _bstr_t 与 CString 相互转换
_bstr_t bstr;
CString strSql;
CString -> _bstr_t: bstr = (_bstr_t)strSql;
_bstr_t -> CString: strSql = (LPCSTR)bstr;
4 、关于时间
Access: 表示时间的字符串 #2004-4-5#
Sql: 表示时间的字符串 ''2004-4-5''
DateField( 时间字段 )
select * from my_table where DateField > #2004-4-10#
try
{
m_pCommand->CommandText = "INSERT INTO tTest( age) VALUES('23f2') ";
m_pRecordset = m_pCommand->Execute(NULL,NULL, adCmdText);
}
catch(_com_error e)/// 捕捉异常
{
CString errormessage;
errormessage.Format(" 连接数据库失败 ! 错误信息 :%s",e.ErrorMessage());
AfxMessageBox(errormessage);/// 显示错误信息
}