VC++中通過ADO中的_RecordsetPtr操作資料庫:增刪改查
_RecordsetPtr智慧指標,它是專門為通過記錄集操作資料庫而設立的指標,通過該介面可以對資料庫的表內的記錄、欄位等進行各種操作。
要搞清楚:資料庫和ADO的記錄集是兩個不同的概念,是存在於不同物理位置的兩個儲存空間。記錄集相當於是實際資料的一份拷貝。正因為記錄集是相對脫離資料庫而存在的,所以才存在後面將要介紹的Open方法中涉及的游標型別和鎖定型別這兩個問題。
_RecordsetPtr介面的使用方法:
先建立記錄集物件:
_ConnectionPtr m_pRecordset;
m_pRecordset.CreateInstance(__uuidof(Recorset));
建立記錄集物件後,只是為它分配記憶體空間,記錄集中不含任何資料。記錄集物件是用來獲得資料庫中的資料並對其操作的,所以還要開啟記錄集,從資料庫中取得資料記錄。可有多種方法開啟記錄集,下面只介紹最常用的Open方法:
為記錄集物件分配了空間後就可以用Open函式開啟記錄集,該函式原型為:
HRESULT Recordset15::Open(const_variant_t& Source,const_variant_t& ActiveConnection,enum CursorTypeEnumCursorType,enum LockTypeEnum LockType,long Options)
引數:
Source是資料查詢字串。
ActiveConnection是已經建立好的連線(我們需要用Connection物件指標來構造一個_variant_t物件)。
CursorType 游標型別,它是列舉CursorTypeEnum中的一個值。
LockType 鎖定型別 它是列舉LockTypeEnum中的一個值
Options 指定Source的型別
游標型別CursorType,可取如下值之一:
adOpenUnspecified=-1 不作特別指定
adOpenForwardOnly=0預設值,前滾靜態游標。這種游標只能向前瀏覽記錄集,比如用MoveNext向前滾動,這種方式可節省資源,提高瀏覽速度,但諸如BookMark、RecordCount、AbsolutePosition、AbsolutePage都不能使用。
adOpenKeyset=1鍵集遊標,採用這種游標的記錄集看不到其它使用者的新增、刪除操作,但對於更新原有記錄的操作對你是可見的。
adOpenDynamic=2動態游標,所有資料庫的操作都會立即在使用者記錄集上反應出來。
adOpenStatic=3靜態遊標。它為記錄產生一個靜態備份,其他使用者的新增、刪除、更新操作對你的記錄集來說是不可見的。
LockType鎖定型別,它可以是以下值之一,請看如下列舉結構
enum LockTypeEnum
{
adLockUnspecified=-1,
//未指定
adLockReadOnly=1,
//只讀記錄集,預設值。無法更改資料。
adLockPessimistic=2,
//悲觀鎖定方式。只有在呼叫Update方法時才鎖定記錄。這是最安全的鎖定機制
adLockOptimistc=3,
//樂觀鎖定方式,只有在你呼叫Update方法時才鎖定記錄。
在此之前仍然可以做資料的更新、插入、刪除等操作
adLockBatchOptimistic=4樂觀分批更新。編輯時記錄不會鎖定,更改、插入及刪除是在批處理模式下完成。
}
關於游標和鎖定型別,對於一般使用者,建議您只作簡單瞭解,後面將進一步進行解說。
Options可以取如下值之一:
adCmdText: 表明CommandText是文字命令。
adCmdTable:表明CommandText是一個表名。
adCmdProc:表明CommandText是一個儲存過程。
adCmdUnknown:未知。
例如:假設m_pConnection是我們已經建立好的連線,我們使用_RecordsetPtr介面的Open方法開啟Employees表的記錄集的語句如下:
m_pRecordset->Open(“SELECT * FROMEmployees”,
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText);
例程RecordsetPtr演示使用_RecordsetPtr指標通過記錄集操作資料庫。
開啟VC++6.0,新建一個基於對話方塊的工程RecordsetPtr。在對話方塊IDD_RECORDSETPTR_DIALOG中進行編輯:
使用三個GroupBox分成四個部分,第一部分演示如何讀取資料庫資料;第二部分演示如何修改資料庫;第三部分演示如何向資料庫中插入資料;第四部分演示如何刪除資料庫中的資料。
使用ClassWizard給列表框IDC_LIST1建立CListBox變數m_list1:
雙擊IDC_BTN_READREC按鈕,並編輯OnBtnReadrec()函式如下:
void CRecordsetPtrDlg::OnBtnReadrec()
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
try
{
m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=Northwind.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("連線資料庫失敗!\r錯誤資訊:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
return;
}
try
{
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open("SELECTEmployeeID,FirstName,LastName,HireDate,City FROM Employees WHERECity='London'",
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText);
}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
}
_variant_tvEmployeeID,vFirstName,vLastName,vHireDate,vCity;
try
{
while(!m_pRecordset->adoEOF)
{
vEmployeeID=m_pRecordset->GetCollect(_variant_t((long)0));
//取得第1列的值,從0開始計數,你也可以直接列出列的名稱,如下一行
vFirstName=m_pRecordset->GetCollect("FirstName");
vLastName=m_pRecordset->GetCollect("LastName");
vHireDate=m_pRecordset->GetCollect("HireDate");
vCity=m_pRecordset->GetCollect("City");
CString strtemp;
if(vEmployeeID.vt!=VT_NULL)
{
strtemp.Format("%d",vEmployeeID.lVal);
}
if(vFirstName.vt!=VT_NULL)
{
strtemp+=" ";
strtemp+=(LPCTSTR)(_bstr_t)vFirstName;
}
if(vLastName.vt!=VT_NULL)
{
strtemp+=" ";
strtemp+=(LPCTSTR)(_bstr_t)vLastName;
}
if(vHireDate.vt!=VT_NULL)
{
strtemp+=" ";
strtemp+=(LPCTSTR)(_bstr_t)vHireDate;
}
if(vCity.vt!=VT_NULL)
{
strtemp+=" ";
strtemp+=(LPCTSTR)(_bstr_t)vCity;
}
m_list1.AddString(strtemp);
m_list1.AddString("\n");
m_pRecordset->MoveNext();
}
}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
}
m_pRecordset->Close();
m_pRecordset=NULL;
m_pConnection->Close();
m_pConnection=NULL;
}
該段程式碼演示瞭如何讀取資料庫表內的資料。其原理是如果沒有遇到表結束標誌adoEOF,則用GetCollect(欄位名)來獲取當前記錄指標所指的欄位值,然後再用MoveNext()方法移動到下一條記錄位置。
雙擊IDC_BTN_CHANGE按鈕,並編輯OnBtnChange()函式如下:
void CRecordsetPtrDlg::OnBtnChange()
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
try
{
m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=Northwind.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("連線資料庫失敗!\r錯誤資訊:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
return;
}
try
{
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open("SELECTEmployeeID,FirstName,LastName,HireDate,City FROM Employees WHERE(City='London') AND (EmployeeID=6)",
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText);
}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
}
try
{
while(!m_pRecordset->adoEOF)
{
m_pRecordset->PutCollect("LastName",_variant_t("Jackson"));
m_pRecordset->MoveNext();
}
m_pRecordset->Update();
}
catch(_com_error* e)
{
AfxMessageBox(e->ErrorMessage());
}
m_pRecordset->Close();
m_pRecordset=NULL;
m_pConnection->Close();
m_pConnection=NULL;
}
該段程式碼演示瞭如何修改記錄中的欄位值:
將記錄指標移動到要修改記錄的位置處,直接用PutCollect(欄位名,值)將新值寫入並Update()更新到資料庫即可。
移動記錄指標可以通過MoveFirst()方法移動到第一條記錄,MoveLast()方法移動到最後一條記錄,MovePrevious()方法移動到當前記錄的前一條記錄,MoveNext()方法移動到當前記錄的下一條記錄。也可以使用Move(記錄號)移動記錄指標到需要位置。注意:Move()方法是相對於當前記錄來移動指標位置的。正值向後移動,負值向前移動。如Move(3),當前記錄是3時,它將從記錄3開始往後再移動3條記錄位置。關於移動記錄指標後面將會用到。
雙擊IDC_BTN_NEW按鈕,並編輯OnBtnNew()函式如下:
void CRecordsetPtrDlg::OnBtnNew()
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
try
{
m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=Northwind.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("連線資料庫失敗!\r錯誤資訊:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
return;
}
try
{
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open("SELECT * FROMEmployees",
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText);
}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
}
try
{
m_pRecordset->MoveLast();
m_pRecordset->AddNew();
m_pRecordset->PutCollect("EmployeeID",_variant_t((long)10));
m_pRecordset->PutCollect("FirstName",_variant_t("Mary"));
m_pRecordset->PutCollect("LastName",_variant_t("Williams"));
m_pRecordset->PutCollect("HireDate",_variant_t("15/4/199312:00:00"));
m_pRecordset->PutCollect("City",_variant_t("NewYork"));
m_pRecordset->PutCollect("Country",_variant_t("USA"));
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
m_pRecordset->Update();
m_pRecordset->Close();
m_pRecordset=NULL;
m_pConnection->Close();
m_pConnection=NULL;
}
該段程式碼演示如何插入記錄:
先用AddNew()方法新增一個空記錄,再用PutCollect(欄位名,值)輸入每個欄位的值,最後用Update()更新到資料庫即可。
雙擊IDC_BTN_DELETE按鈕,並編輯OnBtnDelete()函式如下:
void CRecordsetPtrDlg::OnBtnDelete()
{
_ConnectionPtr m_pConnection;
_RecordsetPtr m_pRecordset;
try
{
m_pConnection.CreateInstance(__uuidof(Connection));
m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=Northwind.mdb","","",adModeUnknown);
}
catch(_com_error e)
{
CString errormessage;
errormessage.Format("連線資料庫失敗!\r錯誤資訊:%s",e.ErrorMessage());
AfxMessageBox(errormessage);
return;
}
try
{
m_pRecordset.CreateInstance("ADODB.Recordset");
m_pRecordset->Open("SELECT * FROMEmployees",
_variant_t((IDispatch*)m_pConnection,true),
adOpenStatic,
adLockOptimistic,
adCmdText);
}
catch(_com_error &e)
{
AfxMessageBox(e.Description());
}
try
{
//假設刪除第10條記錄
m_pRecordset->MoveFirst();
m_pRecordset->Move(9);
m_pRecordset->Delete(adAffectCurrent);
//引數adAffectCurrent為刪除當前記錄
m_pRecordset->Update();
}
catch(_com_error *e)
{
AfxMessageBox(e->ErrorMessage());
}
m_pRecordset->Close();
m_pRecordset=NULL;
m_pConnection->Close();
m_pConnection=NULL;
}
該段程式碼演示瞭如何刪除記錄:
先將記錄指標移動到要刪除的記錄的位置,直接用Delete()方法刪除它,並用Update()來更新資料庫即可。
使用記錄集操作完畢後要關閉記錄集:
直接用Close()方法關閉記錄集並賦予其空值。程式碼如下:
m_pRecordset->Close();
m_pConnection->Close();
m_pRecordset=NULL;
m_pConnection=NULL;