C++ ADO Oracle简述 笔记

有待补充

ADO全称 ActiveX Data Object. 

ActiveX是基于Com技术的。

以下图说明:

 

ADO是微软高度封装的一个基于OLE DB/ODBC 访问各种关系型数据库/非关系型数据库./其他类型文件等。

ADO通过已有的ODBC程序访问各种数据库,理论上只要数据库开发商有提供ODBC驱动程序就可以被ADO进行I/O操作。

 

最近学习如何使用ADO 访问Oracle的知识,做个学习笔记。方便以后再次参考

  Connection对象

在数据库应用里操作数据源都必须通过该对象,这是数据交换的环境。Connection对象代表了同数据源的一个会话,在客户/服务器模型里,这个会话相当于同服务器的一次网络连接。不同的数据提供者提供的该对象的集合、方法和属性不同。

借助于Connection对象的集合、方法和属性,可以使用Open和Close方法建立和释放一个数据源连接。使用Execute方法可以执行一个数据操作命令,使用BeginTrans、CommitTrans和RollbackTrans方法可以启动、提交和回滚一个处理事务。通过操作the Errors 集合可以获取和处理错误信息,操作CommandTimeout属性可以设置连接的溢出时间,操作ConnectionString属性可以设置连接的字符串,操作Mode属性可以设置连接的模式,操作Provider属性可以指定OLE DB提供者。

·       Command对象

Command对象是一个对数据源执行命令的定义,使用该对象可以查询数据库并返回一个Recordset对象,可以执行一个批量的数据操作,可以操作数据库的结构。不同的数据提供者提供的该对象的集合、方法和属性不同。

借助于Command对象的集合、方法和属性,可以使用Parameters集合制定命令的参数,可以使用Execute方法执行一个查询并将查询结果返回到一个Recordset对象里,操作CommandText属性可以为该对象指定一个命令的文本,操作CommandType属性可以指定命令的类型,操作Prepared可以得知数据提供者是否准备好命令的执行,操作CommandTimeout属性可以设置命令执行的溢出时间。

·       Parameter对象

Parameter对象在Command对象中用于指定参数化查询或者存储过程的参数。大多数数据提供者支持参数化命令,这些命令往往是已经定义好了的,只是在执行过程中调整参数的内容。

借助于Parameter对象的集合、方法和属性,可以通过设置Name属性指定参数的名称,通过设置Value属性可以指定参数的值,通过设置Attributes和Direction、Precision、NumericScale、Size与Type 属性可以指定参数的信息,通过执行AppendChunk方法可以将数据传递到参数里。

·       Recordset对象

如果执行的命令是一个查询并返回存放在表中的结果集,这些结果集将被保存在本地的存储区里,Recordset对象是执行这种存储的ADO对象。通过Recordset对象可以操纵来自数据提供者的数据,包括修改和更新行、插入和删除行。

 

ADO定义了如表

光标类型

描述

adOpenDynamic

允许添加、修改和删除记录,支持所有方式的光标移动,其他用户的修改可以在联机以后仍然可见

adOpenKeyset

类似于adOpenDynamic光标,它支持所有类型的光标移动,但是建立连接以后其他用户对记录的添加不可见,其他用户对记录的删除和对数据的修改是可见的。支持书签操作

adOpenStatic

支持各种方式的光标移动,但是建立连接以后其他用户的行添加、行删除和数据修改都不可见,支持书签操作

adOpenForwardOnly

只允许向前存取,而且在建立连接以后,其他用户的行添加、行删除和数据修改都不可见,支持书签操作

ADO定义了如表

锁定类型

描述

adLockReadOnly

(缺省)数据只读

adLockPessimistic

锁定操作的所有行,也称为消极锁定

adLockOptimistic

只在调用Update方法时锁定操作的行,也称为积极锁定

adLockBatchOptimistic

在批量更新时使用该锁定,也称为积极批量锁定

ADO定义了如表

光标服务位置

描述

adUseNone

不使用光标服务位置

adUseClient

使用客户端光标

adUseServer

(缺省)使用数据服务端或者驱动提供端光标

借助于Recordset对象的集合、方法和属性,可以通过设置CursorType属性设置记录集的光标类型,通过设置CursorLocation属性可以指定光标位置,通过读取BOF 和EOF属性的值,获知当前光标在记录集里的位置是在最前或者最后,通过执行MoveFirst、MoveLast、MoveNext和MovePrevious 方法移动记录集里的光标,通过执行Update方法可以更新数据修改,通过执行AddNew方法可以执行行插入操作,通过执行Delete方法可以删除行。

·       Field对象

Recordset对象的一个行由一个或者多个Fields对象组成,如果把一个Recordset对象看成一个二维网格表,那么Fields对象就是这些列。这些列里保存了列的名称、数据类型和值,这些值是来自数据源的真正数据。为了修改数据源里的数据,必须首先修改Recordset对象各个行里Field对象里的值,最后Recordset对象将这些修改提交到数据源。

借助于Field对象的集合、方法和属性,可以通过读取Name属性,获知列的名称。通过操作Value属性可以改变列的值,通过读取Type、Precision和NumericScale 属性,可获知列的数据类型、精度和小数位的个数,通过执行AppendChunk 和GetChunk 方法可以操作列的值。

·       Error对象

Error对象包含了ADO数据操作时发生错误的详细描述,ADO的任何对象都可以产生一个或者多个数据提供者错误,当错误发生时,这些错误对象被添加到Connection 对象的Errors集合里。当另外一个ADO对象产生一个错误时,Errors集合里的Error对象被清除,新的Error对象将被添加到Errors集合里。

借助于Errosr对象的集合、方法和属性,可以通过读取Number和Description属性,获得ADO错误号码和对错误的描述,通过读取Source属性得知错误发生的源。

·       Property对象

Property对象代表了一个由提供者定义的ADO对象的动态特征。ADO对象有两种类型的Property对象:内置的和动态的。内置的Property对象是指那些在ADO里实现的在对象创建时立即可见的属性,可以通过域作用符直接操作这些属性。动态的Property对象是指由数据提供者定义的底层的属性,这些属性出现在ADO对象的Properties集合里,例如,如果一个Recordset 对象支持事务和更新,这些属性将作为Property对象出现在Recordset对象的Properties集合里。动态属性必须通过集合进行引用,比如使用下面的语法:

        MyObject.Properties(0)   

或者

        MyObject.Properties("Name")

不能删除任何类型的属性对象。借助于Property对象的集合、方法和属性,可以通过读取Name属性获得属性的名称,通过读取Type属性获取属性的数据类型,通过读取Value属性获取属性的值。

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);/// 显示错误信息

}

 

转载于:https://www.cnblogs.com/emjx/p/11285830.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值