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. }  

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