ODBC中怎么利用CRecordset類對數(shù)據(jù)庫進行操作,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
成都創(chuàng)新互聯(lián)憑借在網(wǎng)站建設、網(wǎng)站推廣領域領先的技術能力和多年的行業(yè)經(jīng)驗,為客戶提供超值的營銷型網(wǎng)站建設服務,我們始終認為:好的營銷型網(wǎng)站就是好的業(yè)務員。我們已成功為企業(yè)單位、個人等客戶提供了成都網(wǎng)站建設、網(wǎng)站建設服務,以良好的商業(yè)信譽,完善的服務及深厚的技術力量處于同行領先地位。
1.MFC中的ODBC類
主要有CDatabase、CRecordset、CRecordview、CDBException、CFieldExchange。這些類封裝了ODBC
SDK函數(shù),可以很方便的操作支持ODBC的數(shù)據(jù)庫。
(1)CDatabase類:封裝應用程序與需要訪問的數(shù)據(jù)庫之間的連接,控制事務的提交和執(zhí)行SQL語句的方法。
(2)CRecordset類:封裝大部分操縱數(shù)據(jù)庫的方法,包括瀏覽、修改記錄、控制游標移動,排序等操作。CRecordset類是MFC的ODBC類中最重要、功能最強大的一個類。CRecordset類對象提供了從數(shù)據(jù)源中提取出的記錄集。在多任務操作系統(tǒng)或網(wǎng)絡環(huán)境中,多個用戶可以共享同一個數(shù)據(jù)源。共享數(shù)據(jù)的一個主要問題是如何協(xié)調(diào)各個用戶對數(shù)據(jù)源的修改。CRecordset提供了幾種不同的方法來處理這個問題,這將由程序采用哪種類型的記錄集來決定。
CRecordset對象通常用于兩種形式:動態(tài)行集(dynasets)和快照集(snapshots)。動態(tài)行集能與其他用戶所做的更改保持同步,快照集則是數(shù)據(jù)的一個靜態(tài)視圖,當別的用戶改變了記錄時(包括修改、添加和刪除),快照中的記錄不受影響,也就是說,快照不反映別的用戶對數(shù)據(jù)源記錄的改變.直到調(diào)用了CRecordset::Requery重新查詢后,快照才會反映變化。每一種形式在記錄集被打開時都提供一組記錄,所不同的是,當在一個動態(tài)行集里滾動到一條記錄時,由其他用戶或是應用程序中其他記錄集對該記錄所做的更改會相應地顯示出來,例如在火車聯(lián)網(wǎng)銷售系統(tǒng)中,應該實時的顯示共享數(shù)據(jù)的變化。
(3)CRecordView類:提供與CRecordset對象相連接的視圖,可以建立視圖中的控件與數(shù)據(jù)庫數(shù)據(jù)的對應,同時支持游標,修改記錄等操作。
(4)CDBException類:提供對數(shù)據(jù)庫操作的異常處理。
(5)CFieldExchange類:提供用戶變量與數(shù)據(jù)庫字段之間的數(shù)據(jù)交換。
2.域數(shù)據(jù)成員與數(shù)據(jù)交換
CRecordset類代表一個記錄集。用戶一般用ClassWizard創(chuàng)建一個CRecordset的派生類。ClassWizard可以為派生的記錄集類創(chuàng)建一批數(shù)據(jù)成員,這些數(shù)據(jù)成員與記錄的各字段相對應,被稱為字段數(shù)據(jù)成員或域數(shù)據(jù)成員。域數(shù)據(jù)成員與表中的字段名字類似,且類型匹配。
例如:這是一個CRecordset類的派生類的定義
class CSetdata : public CRecordset
{
public:
CSetdata(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CSetdata)
// Field/Param Data
//{{AFX_FIELD(CSetdata, CRecordset)
//定義域數(shù)據(jù)成員變量,域數(shù)據(jù)成員用來與記錄集對應字段進行數(shù)據(jù)交換,起到一個緩沖區(qū)或中間橋梁的作用。也就是說,我們在處理記錄集時,實際上是對域數(shù)據(jù)成員進行操作,而不是直接對數(shù)據(jù)庫中的數(shù)據(jù)操作。
CString m_number;
CString m_name;
CString m_sex;
long m_age;
//}}AFX_FIELD
CString number;
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CSetdata)
public:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // Default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX support
//}}AFX_VIRTUAL
// Implementation
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
};
#endif
域數(shù)據(jù)成員用來保存某條記錄的各個字段,它們是程序與記錄之間的緩沖區(qū)。域數(shù)據(jù)成員代表當前記錄,當在記錄集中滾動到某一記錄時,框架自動地把記錄的各個字段拷貝到記錄集對象的域數(shù)據(jù)成員中。當用戶要修改當前記錄或增加新記錄時,程序先將各字段的新值放入域數(shù)據(jù)成員中,然后調(diào)用相應的CRecordset成員函數(shù)把域數(shù)據(jù)成員設置到數(shù)據(jù)源中。
不難看出,在記錄集與數(shù)據(jù)源之間有一個數(shù)據(jù)交換問題.CRecordset類使用"記錄域交換"(Record Field Exchange,縮寫為RFX)機制自動地在域數(shù)據(jù)成員和數(shù)據(jù)源之間交換數(shù)據(jù)。RFX機制與對話數(shù)據(jù)交換(DDX)類似。CRecordset的成員函數(shù)DoFieldExchange負責數(shù)據(jù)交換任務,在該函數(shù)中調(diào)用了一系列RFX函數(shù)。當用戶用ClassWizard加入域數(shù)據(jù)成員時,ClassWizard會自動在DoFieldExchange中建立RFX。
典型的DoFieldExchange函數(shù)
void CSetdata::DoFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CSetdata)
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, _T("[number]"), m_number); //實現(xiàn)了域數(shù)據(jù)成員和數(shù)據(jù)源之間的數(shù)據(jù)交換
RFX_Text(pFX, _T("[name]"), m_name);
RFX_Text(pFX, _T("[sex]"), m_sex);
RFX_Long(pFX, _T("[age]"), m_age);
//}}AFX_FIELD_MAP
pFX->SetFieldType(CFieldExchange::param);
RFX_Text(pFX,_T("[]"),number);
}
3.記錄集的建立和關閉
使用MFC的ODBC類操作數(shù)據(jù)庫首先要建立一個CRecordset的派生類來關聯(lián)對應的數(shù)據(jù)表,然后調(diào)用Open()函數(shù)來查詢數(shù)據(jù)源中的數(shù)據(jù)并建立記錄集。此外,在Open函數(shù)中,可能還會調(diào)用GetDefaultConnect和GetDefaultSQL函數(shù)。
(1)首先在派生類的構造函數(shù)中會有一個參數(shù)指向一個CDatabase對象,用來獲取數(shù)據(jù)源。函數(shù)如下:
CRecordset(CDatabase* pDatabase = NULL);
如果pDatabase為NULL,則會在Open函數(shù)中自動構建一個CDatabase對象。如果CDatabase對象還未與數(shù)據(jù)源連接,那么在Open函數(shù)中會建立連接,連接字符串由成員函數(shù)GetDefaultConnect提供。
(2)virtual CString GetDefaultConnect();
該函數(shù)返回缺省的連接字符串。Open函數(shù)在必要的時侯會調(diào)用該函數(shù)獲取連接字符串以建立與數(shù)據(jù)源的連接。一般需要在CRecordset派生類中覆蓋該函數(shù)并在新版的函數(shù)中提供連接字符串。
例如:CSetdata為CRecordset類的派生類
CString CSetdata::GetDefaultConnect()
{
return _T("ODBC;DSN=my data");
}
這個函數(shù)獲取了數(shù)據(jù)庫連接字符串,包括連接方式以及數(shù)據(jù)源的名稱。
(3)virtual CString GetDefaultSQL();
Open函數(shù)在必要時會調(diào)用該函數(shù)返回缺省的SQL語句或表名以查詢數(shù)據(jù)源中的記錄。一般需要在CRecordset派生類中覆蓋該函數(shù)并在新版的函數(shù)中提供SQL語句或表名。
例如:
CString CSetdata::GetDefaultSQL()
{
return _T("[bingli]");
}
這個類返回的是數(shù)據(jù)源中數(shù)據(jù)表bingli的名稱。
(4)virtual BOOL Open( UINT nOpenType = AFX_DB_USE_DEFAULT_TYPE, LPCTSTR lpszSQL = NULL, DWORD dwOptions = none );
throw( CDBException, CMemoryException );
該函數(shù)使用指定的SQL語句查詢數(shù)據(jù)源中的記錄并按指定的類型和選項建立記錄集。參數(shù)nOpenType說明了記錄集的類型,如下表所示。如果要求的類型驅動程序不支持,則函數(shù)將產(chǎn)生一個異常。參數(shù)lpszSQL是一個SQL的SELECT語句,或是一個表名。函數(shù)用lpszSQL來進行查詢,如果該參數(shù)為NULL,則函數(shù)會調(diào)用GetDefaultSQL獲取缺省的SQL語句。參數(shù)dwOptions可以是一些選項的組合,常用的選項在下表中列出。若創(chuàng)建成功則函數(shù)返回TRUE,若函數(shù)調(diào)用了CDatabase::Open且返回FALSE,則函數(shù)返回FALSE.
記錄集的類型
類型
含義
AFX_DB_USE_DEFAULT_TYPE 使用缺省值.
CRecordset::dynaset 可雙向滾動的動態(tài)集.
CRecordset::snapshot 可雙向滾動的快照.
CRecordset::dynamic 提供比動態(tài)集更好的動態(tài)特性,大部分ODBC驅動程序不支持這種記錄集.
CRecordset::forwardOnly 只能前向滾動的只讀記錄集.
創(chuàng)建記錄集時的常用選項
選項
含義
CRecordset::none 無選項(缺省).
CRecordset::appendOnly 不允許修改和刪除記錄,但可以添加記錄.
CRecordset::readOnly 記錄集是只讀的.
CRecordset::skipDeletedRecords 有些數(shù)據(jù)庫(如FoxPro)在刪除記錄時并不真刪除,而是做個刪除標記,在滾動時將跳過這些被刪除的記錄。
如果所有的參數(shù)都為空,例如:
CSetdata *pset = new CSetdata();
pset->Open();
那么Open()函數(shù)將會調(diào)用GetDefaultSQL()函數(shù)獲取指定數(shù)據(jù)表的數(shù)據(jù)并建立數(shù)據(jù)集。實際上,如果只提供表名,CRecordset類會構造一個SELECT語句來查詢數(shù)據(jù)源。例如:SELECT
(能提供的字段名) FROM bingli(即GetDefaultSQL()函數(shù)返回的表名)。
(5) 建立記錄集后,用戶可以隨時調(diào)用Requery成員函數(shù)來重新查詢和建立記錄集。Requery有兩個重要用途:
使記錄集能反映用戶對數(shù)據(jù)源的改變
按照新的過濾或排序方法查詢記錄并重新建立記錄集.
在調(diào)用Requery之前,可調(diào)用CanRestart來判斷記錄集是否支持Requery操作。要記住Requery只能在成功調(diào)用Open后調(diào)用,所以程序應調(diào)用IsOpen來判斷記錄集是否已建立.函數(shù)的聲明為
virtual BOOL Requery( );
throw( CDBException, CMemoryException );
返回TRUE表明記錄集建立成功,否則返回FALSE。若函數(shù)內(nèi)部出錯則產(chǎn)生異常.
BOOL CanRestart( ) const; //若支持Requery則返回TRUE
BOOL IsOpen( ) const; //若記錄集已建立則返回TRUE
CRecordset類有兩個公共數(shù)據(jù)成員m_strFilter和m_strSort用來設置對記錄的過濾和排序。在調(diào)用Open或Requery前,如果在這兩個數(shù)據(jù)成員中指定了過濾或排序,那么Open和Requery將按這兩個數(shù)據(jù)成員指定的過濾和排序來查詢數(shù)據(jù)源。
成員m_strFilter用于指定過濾器。m_strFilter實際上包含了SQL的WHERE子句的內(nèi)容,但它不含WHERE關鍵字。使用m_strFilter的一個例子為:
m_pSet->m_strFilter=“CourseID=‘MATH101’”; //只選擇CourseID為MATH101的記錄
if(m_pSet->Open(CRecordset::snapshot, “Section”))
. . . . . .
成員m_strSort用于指定排序.m_strSort實際上包含了ORDER BY子句的內(nèi)容,但它不含ORDER BY關鍵字.m_strSort的一個例子為
m_pSet->m_strSort=“CourseID DESC”; //按CourseID的降序排列記錄
m_pSet->Open();
. . . . . .
事實上,Open函數(shù)在構造SELECT語句時,會把m_strFilter和m_strSort的內(nèi)容放入SELECT語句的WHERE和ORDER
BY子句中.如果在Open的lpszSQL參數(shù)中已包括了WHERE和ORDER BY子句,那么m_strFilter和m_strSort必需為空.
調(diào)用無參數(shù)成員函數(shù)Close可以關閉記錄集.在調(diào)用了Close函數(shù)后,程序可以再次調(diào)用Open建立新的記錄集.CRecordset的析構函數(shù)會調(diào)用Close函數(shù),所以當刪除CRecordset對象時記錄集也隨之關閉。
4.滾動記錄
CRecordset提供了幾個成員函數(shù)用來在記錄集中滾動,如下所示.當用這些函數(shù)滾動到一個新記錄時,框架會自動地把新記錄的內(nèi)容拷貝到域數(shù)據(jù)成員中。
void MoveNext(); //前進一個記錄
void MovePrev(); //后退一個記錄
void MoveFirst(); //滾動到記錄集中的第一個記錄
void MoveLast(); //滾動到記錄集中的最后一個記錄
void SetAbsolutePosition( long nRows );
該函數(shù)用于滾動到由參數(shù)nRows指定的絕對位置處.若nRows為負數(shù),則從后往前滾動.例如,當nRows為-1時,函數(shù)就滾動到記錄集的末尾。注意,該函數(shù)不會跳過被刪除的記錄。
virtual void Move( long nRows, WORD wFetchType = SQL_FETCH_RELATIVE );
該函數(shù)功能強大.通過將wFetchType參數(shù)指定為SQL_FETCH_NEXT、SQL_FETCH_PRIOR、SQL_FETCH_FIRST、SQL_FETCH_LAST和SQL_FETCH_ABSOLUTE,可以完成上面五個函數(shù)的功能.若wFetchType為SQL_FETCH_RELATIVE,那么將相對當前記錄移動,若nRows為正數(shù),則向前移動,若nRows為負數(shù),則向后移動。
如果在建立記錄集時選擇了CRecordset::skipDeletedRecords選項,那么除了SetAbsolutePosition外,在滾動記錄時將跳過被刪除的記錄,這一點對象FoxPro這樣的數(shù)據(jù)庫十分重要。
如果記錄集是空的,那么調(diào)用上述函數(shù)將產(chǎn)生異常。另外,必須保證滾動沒有超出記錄集的邊界。調(diào)用IsEOF和IsBOF可以進行這方面的檢測。
BOOL IsEOF( ) const; //如果記錄集為空或滾動過了最后一個記錄,那么函數(shù)返回TRUE,否則返回FALSE。
BOOL IsBOF( ) const; //如果記錄集為空或滾動過了第一個記錄,那么函數(shù)返回TRUE,否則返回FALSE。
下面是一個使用IsEOF的例子:
while(!m_pSet->IsEOF( ))
m_pSet->MoveNext( );
調(diào)用GetRecordCound可獲得記錄集中的記錄總數(shù),該函數(shù)的聲明為:
long GetRecordCount( ) const;
要注意這個函數(shù)返回的實際上是用戶在記錄集中滾動的最遠距離.要想真正返回記錄總數(shù),只有調(diào)用MoveNext移動到記錄集的末尾(MoveLast不行)。
5.修改、添加和刪除記錄
要修改當前記錄,應該按下列步驟進行:
調(diào)用Edit成員函數(shù).調(diào)用該函數(shù)后就進入了編輯模式,程序可以修改域數(shù)據(jù)成員.注意不要在一個空的記錄集中調(diào)用Edit,否則會產(chǎn)生異常.
Edit函數(shù)會把當前域數(shù)據(jù)成員的內(nèi)容保存在一個緩沖區(qū)中,這樣做有兩個目的,一是可以與域數(shù)據(jù)成員作比較以判斷哪些字段被改變了,二是在必要的時侯可以恢復域數(shù)據(jù)成員原來的值.若再次調(diào)用Edit,則將從緩沖區(qū)中恢復域數(shù)據(jù)成員,調(diào)用后程序仍處于編輯模式.調(diào)用Move(AFX_MOVE_REFRESH)或Move(0)可退出編輯模式(AFX_MOVE_REFRESH的值為0),同時該函數(shù)會從緩沖區(qū)中恢復域數(shù)據(jù)成員.
設置域數(shù)據(jù)成員的新值.
調(diào)用Update完成編輯.Update把變化后的記錄寫入數(shù)據(jù)源并結束編輯模式.
要向記錄集中添加新的記錄,應該按下列步驟進行:
調(diào)用AddNew成員函數(shù).調(diào)用該函數(shù)后就進入了添加模式,該函數(shù)把所有的域數(shù)據(jù)成員都設置成NULL(注意,在數(shù)據(jù)庫術語中,NULL是指沒有值,這與C++的NULL是不同的).與Edit一樣,AddNew會把當前域數(shù)據(jù)成員的內(nèi)容保存在一個緩沖區(qū)中,在必要的時侯,程序可以再次調(diào)用AddNew取消添加操作并恢復域數(shù)據(jù)成員原來的值,調(diào)用后程序仍處于添加模式.調(diào)用Move(AFX_MOVE_REFRESH)可退出添加模式,同時該函數(shù)會從緩沖區(qū)中恢復域數(shù)據(jù)成員.
設置域數(shù)據(jù)成員.
調(diào)用Update.Update把域數(shù)據(jù)成員中的內(nèi)容作為新記錄寫入數(shù)據(jù)源,從而結束了添加.
如果記錄集是快照,那么在添加一個新的記錄后,需要調(diào)用Requery重新查詢,因為快照無法反映添加操作.
要刪除記錄集的當前記錄,應按下面兩步進行:
調(diào)用Delete成員函數(shù).該函數(shù)會同時給記錄集和數(shù)據(jù)源中當前記錄加上刪除標記.注意不要在一個空記錄集中調(diào)用Delete,否則會產(chǎn)生一個異常.
滾動到另一個記錄上以跳過刪除記錄.
上面提到的函數(shù)聲明為:
virtual void Edit( );throw( CDBException, CMemoryException );
virtual void AddNew( );throw( CDBException );
virtual void Delete( );throw( CDBException );
virtual BOOL Update( );throw( CDBException );
若更新失敗則函數(shù)返回FALSE,且會產(chǎn)生一個異常.
在對記錄集進行更改以前,程序也許要調(diào)用下列函數(shù)來判斷記錄集是否是可以更改的,因為如果在不能更改的記錄集中進行修改、添加或刪除將導致異常的產(chǎn)生.
BOOL CanUpdate( ) const; //返回TRUE表明記錄是可以修改、添加和刪除的.
BOOL CanAppend( ) const; //返回TRUE則表明可以添加記錄.
關于ODBC中怎么利用CRecordset類對數(shù)據(jù)庫進行操作問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關知識。
網(wǎng)頁標題:ODBC中怎么利用CRecordset類對數(shù)據(jù)庫進行操作
當前地址:http://www.ekvhdxd.cn/article4/ghdgoe.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設計公司、靜態(tài)網(wǎng)站、品牌網(wǎng)站制作、建站公司、網(wǎng)站收錄、電子商務
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)