VC中使用ADO操作数据库的方法(比较详细)

参考:http://blog.csdn.net/augusdi/article/details/7005597,做了部分补充和删除

准备工作:

(1)、引入ADO类

#import "c:\program files\common files\system\ado\msado15.dll"  no_namespace rename ("EOF", "adoEOF")

(2)、初始化COM

在MFC中可以用  AfxOleInit();

非MFC环境中用  CoInitialize(NULL);/ CoUnInitialize();

(3)#import 包含后就可以用3个智能指针了:_ConnectionPtr、_RecordsetPtr和_CommandPtr

使用步骤:

1. 连接和关闭数据库

(1)连接

例子:连接Access数据库

[cpp] view plain copy
  1. //初始化  
  2. AfxOleInit();  
  3.   
  4. HRESULT hr;  
  5. try  
  6. {  
  7.     ///创建Connection对象  
  8.     hr = m_pConnection.CreateInstance("ADODB.Connection");  
  9.     if(SUCCEEDED(hr))  
  10.     {  
  11.         m_pConnection->ConnectionTimeout = 0;  
  12.         hr = m_pConnection->Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=db.mdb""""", adModeUnknown);  
  13.         //m_pConnection->PutDefaultDatabase ((_bstr_t)"DB"); //设置默认数据库  
  14.         m_pCommand.CreateInstance(__uuidof(Command));  
  15.         m_pCommand->CommandTimeout = 5;  
  16.         m_pCommand->ActiveConnection = m_pConnection;  
  17.     }  
  18. }  
  19. catch(_com_error e)///捕捉异常  
  20. {  
  21.     CString errormessage;  
  22.     errormessage.Format(" 连接数据库失败! 错误信息:%s",e.ErrorMessage());  
  23.     AfxMessageBox(errormessage);///显示错误信息  
  24. }  

(2)、关闭

[cpp] view plain copy
  1. //如果数据库连接有效  
  2. if( m_pConnection->State )  
  3. m_pConnection->Close();  
  4. m_pConnection = NULL;   

(3)、设置连接时间

[cpp] view plain copy
  1. //设置连接时间  
  2. pConnection->put_ConnectionTimeout(long(5));  

2.打开一个结果集

(1) 打开,首先创建一个_RecordsetPtr实例,然后调用Open()得到一条SQL语句的执行结果

[cpp] view plain copy
  1. _RecordsetPtr m_pRecordset;  
  2. m_pRecordset.CreateInstance(__uuidof(Recordset));  
  3. try  
  4. {  
  5.     m_pRecordset->Open("SELECT * FROM DemoTable",// 查询DemoTable表中所有字段  
  6.                         m_pConnection.GetInterfacePtr(), // 获取库接库的IDispatch指针  
  7.                         adOpenDynamic,  
  8.                         adLockOptimistic,  
  9.                         adCmdText);  
  10. }  
  11. catch(_com_error *e)  
  12. {  
  13.     AfxMessageBox(e->ErrorMessage());  
  14. }   

(2) 关闭结果集
m_pRecordset->Close();

3. 操作一个结果集

(1)、遍历(读取)

a)、用pRecordset->adoEOF来判断数据库指针是否已经移到结果集的末尾了;

m_pRecordset->BOF判断是否在第一条记录前面:

[cpp] view plain copy
  1. while(!m_pRecordset->adoEOF)  
  2. {  
  3.     //获取字段值  
  4.     _variant_t var = m_pRecordset->GetCollect("Name");  
  5.     if(var.vt != VT_NULL)  
  6.     {  
  7.         CString strName = (LPCSTR)_bstr_t(var);  
  8.     }  
  9.       
  10.     var = m_pRecordset->GetCollect("Age");  
  11.     if(var.vt != VT_NULL)  
  12.     {  
  13.         CString strAge = (LPCSTR)_bstr_t(var);  
  14.     }  
  15.   
  16.     m_pRecordset->MoveNext();  
  17. }   

b)、取得一个字段的值的办法有两种办法

第一种:

//表示取得第0个字段的值
rdset->GetCollect("Name");
// 或者
rdset->GetCollect(_variant_t(long(0));

第二种

pRecordset->get_Collect("COLUMN_NAME");
//或者 
pRecordset->get_Collect(long(index));

(2)、添加

调用m_pRecordset->AddNew();

调用m_pRecordset->PutCollect();给每个字段赋值

调用m_pRecordset->Update();确认

(3)、修改

调用m_pRecordset->PutCollect();给每个字段赋值

调用m_pRecordset->Update();确认

(4)、删除

把记录指针移动到要删除的记录上,然后调用Delete(adAffectCurrent)

[cpp] view plain copy
  1. try  
  2. {  
  3.     // 假设删除第二条记录  
  4.     m_pRecordset->MoveFirst();  
  5.     //从当前位置向下移动一条记录  
  6.     m_pRecordset->Move(1);   
  7.     //参数adAffectCurrent 为删除当前记录  
  8.     m_pRecordset->Delete(adAffectCurrent);   
  9.     m_pRecordset->Update();  
  10. }  
  11. catch(_com_error *e)  
  12. {  
  13.     AfxMessageBox(e->ErrorMessage());  
  14. }  

4. 直接执行SQL语句

(1)、用_CommandPtr和_RecordsetPtr配合

[cpp] view plain copy
  1. _CommandPtr m_pCommand;  
  2. m_pCommand.CreateInstance(__uuidof(Command));  
  3. // 将库连接赋于它  
  4. m_pCommand->ActiveConnection = m_pConnection;   
  5. // SQL语句  
  6. m_pCommand->CommandText = "SELECT * FROM DemoTable";   
  7. // 执行SQL语句,返回记录集  
  8. m_pRecordset = m_pCommand->Execute(NULL, NULL,adCmdText);   

(2)、直接用_ConnectionPtr执行SQL语句

_RecordsetPtr Connection::Execute ( _bstr_t CommandText, VARIANT * RecordsAffected, long Options )

参数:

RecordsAffected是操作完成后所影响的行数;

Options表示CommandText中内容的类型,Options可以取如下值之一:

adCmdText:表明CommandText是文本命令,通常是SQL语句;

adCmdTable:表明CommandText是一个表名;

adCmdProc:表明CommandText是一个存储过程

adCmdUnknown:未知,或默认

[cpp] view plain copy
  1. try   
  2. {   
  3.     m_pCommand->CommandText ="INSERT INTO tTest(age) VALUES('23f2') ";   
  4.     m_pRecordset = m_pCommand->Execute(NULL,NULL, <span style="color:#66cccc;">adCmdText</span>);   
  5. }  
  6. //捕捉异常   
  7. catch(_com_error e)  
  8. {  
  9.     //显示错误信息   
  10.     AfxMessageBox(e.ErrorMessage());  
  11. }  

5. 调用存储过程

(1)、利用_CommandPtr

[cpp] view plain copy
  1. _CommandPtrm_pCommand;  
  2. m_pCommand.CreateInstance(__uuidof(Command));  
  3. //将库连接赋于它  
  4. m_pCommand->ActiveConnection = m_pConnection;   
  5. m_pCommand->CommandText = "Demo";   
  6. m_pCommand->Execute(NULL,NULL, <span style="color:#ff6666;">adCmdStoredProc</span>);   

(2)、直接用_ConnectionPtr直接调用

特殊应用:

显示数据库、表信息

使用_ConnectionPtr 的成员函数openSchema()可以获取数据库的模式信息;

函数原型:

_RecordsetPtr recordset = connection.OpenSchema (QueryType, Criteria, SchemaID)
参数:

1. QueryType

SchemaEnum枚举类型的值,指出获取模式(Schema)的类型;

2. Criteria

可选项,对应SchemaEnum的查询选项

3. SchemaID

可选项,仅当 QueryType 被设置为adSchemaProviderSpecific 的时候才有用,否则不使用该参数; 

SchemeEnum枚举类型的常用取值如下:

adSchemaColumns:返回用户可访问的数据库目录中表的列名(包括视图View);

返回结果集中的列名(字段名):

TABLE_CATALOG
TABLE_SCHEMA
TABLE_NAME
COLUMN_NAME

adSchemaTables:返回用户可访问的数据库目录中的表名;

返回结果集中的列名(字段名):

TABLE_CATALOG
TABLE_SCHEMA
TABLE_NAME
TABLE_TYPE

示例1:遍历数据库中的所有表名;

[cpp] view plain copy
  1. _ConnectionPtr m_pConnect;  
  2. _RecordsetPtr pSet;  
  3. HRESULT hr;  
  4. try  
  5. {   
  6.     hr = m_pConnect.CreateInstance("ADODB.Connection");   
  7.     if(SUCCEEDED(hr))   
  8.     {  
  9.         CString dd;   
  10.         dd.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%s",file);  
  11.         hr=m_pConnect->Open((_bstr_t)dd, """", adModeUnknown);   
  12.         pSet=m_pConnect->OpenSchema(adSchemaTables);   
  13.         while(!(pSet->adoEOF))   
  14.         {   
  15.             //获取表格名称  
  16.             _bstr_t table_name = pSet->Fields->GetItem("TABLE_NAME")->Value;  
  17.             //获取表格类型  
  18.             _bstr_t table_type = pSet->Fields->GetItem("TABLE_TYPE")->Value;  
  19.             //过滤一下,只输出表格名称,其他的省略  
  20.             if(strcmp(((LPCSTR)table_type),"TABLE")==0)  
  21.             {  
  22.                 CString tt;  
  23.                 tt.Format("%s",(LPCSTR)table_name);   
  24.                 AfxMessageBox(tt);   
  25.             }   
  26.             pSet->MoveNext();   
  27.         }   
  28.         pSet->Close();   
  29.     }   
  30.   
  31.     m_pConnect->Close();   
  32. }  
  33. //捕捉异常  
  34. catch(_com_error e)  
  35. {  
  36.     AfxMessageBox(e.ErrorMessage());  
  37. }  

示例2:遍历一个表中的所有字段

[cpp] view plain copy
  1. HRESULT hr;  
  2. Fields * fields = NULL;  
  3. //得到记录集的字段集,并存储在fields中  
  4. hr=m_pRecordset->get_Fields(&fields);  
  5.   
  6. if(SUCCEEDED(hr))  
  7. {  
  8.     //得到记录集的字段集合中的字段的总个数  
  9.     fields->get_Count(&ColCount);  
  10.   
  11.     for(i=0;i ...  
  12.     {  
  13.         Item[i]->get_Name(&bstrColName);//得到记录集//中的字段名  
  14.         strColName=bstrColName;  
  15.         nameField = strColName;  
  16.         m_FieldsList.AddString(nameField);  
  17.     }  
  18.     if(SUCCEEDED(hr))  
  19.     {  
  20.         fields->Release();//释放指针   
  21.     }  
  22. }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章