背景
接觸C++以來,因為之前學的java做Web時經常要和數據庫打交道,所以也就一直想用C++來操作數據庫。之前也聽過ODBC數據源的方法聽說比較麻煩,C++用ADO的方法連接數據比較方便。
下面就是具體的步驟和代碼了。
1.導入ADO的庫
使用ADO的話必須要導入它的庫,這語句放到頭文件.h中,因為我這里是用的MFC程序建的工程,所以我放在stdafx.h頭文件中
//導入ADO的庫
#import "C:\\Program Files\\Common Files\\System\\ado\\msado15.dll" no_namespace rename("EOF","adoEOF")
文件msado15.dll可以在你的電腦中的相應路徑C:\Program Files\Common Files\System\ado找到;no_namespace 表示沒有命名空間,可以不寫不過后面的ADO對象要加上ADODB::引入;rename("EOF","adoEOF")是用adoEOF替換EOF ,如果你用到BOF的話也可以通過這種方式替換。
2.在頭文件中定義成員變量和成員函數
在AdoDlg.h文件中:
//定義變量 _ConnectionPtr m_conn; //連接智能指針 _RecordsetPtr m_rec;//記錄集智能指針 HRESULT hr; // //列表控件變量 CListCtrl m_listCtrl; //函數 bool AdoOpen(char* userName,char* pwd,char* conStr,char* errStr); //連接數據庫 //_RecordsetPtr AdoExucute(char* sqlStr); //執行sql語句,操作表 bool AdoClose();//關閉數據庫 void InsertCol();//插入表頭 void GetRecordSet();//獲得記錄集 void AdoQuery();//查詢數據 bool AdoAdd();//增加數據 bool AdoUpdate();//修改數據 bool AdoDelete();//刪除數據
3.在使用ADO前要初始化COM類庫環境
在AdoDlg.cpp文件中:
a.在構造函數中初始化成員變量
m_conn=NULL;
b.在OnInitDialog()函數中
//初始化COM類庫
//CoInitialize返回的是HRESULT類型的值,返回S_OK(值為0)表示COM初始化成功,
// 返回S_FALSE(值為1)表示當前線程已經初始化過COM,所以返回S_OK或S_FALSE都是對的
/*if(FAILED(::CoInitialize(NULL)))
{
MessageBox("初始化COM庫失敗");
return FALSE;
}*/
AfxOleInit();//MFC工程建議用AfxOleInit();//控制台建議用CoInitalize(),同時在Close函數或是析構函數中記得調用::CoUninitialize();卸載COM環境;
//MFC工程建議用AfxOleInit();就行了。
4.實現成員函數
a .建立與數據庫的連接
//連接數據庫
bool CAdoDBDlg:: AdoOpen(char* userName,char* pwd,char* conStr,char* errStr)
{
//捕獲異常
try{
//創建Connection對象的一個實例
hr=m_conn.CreateInstance(_uuidof(Connection));///創建Connection對象
//通過用戶名、密碼以及連接字符串連接數據庫
m_conn->Open(conStr,userName,pwd,NULL);
}catch(_com_error e)
{
MessageBox(e.ErrorMessage());
}
return TRUE;
}
b.獲得查詢的結果集
//獲取結果集
void CAdoDBDlg::GetRecordSet()
{
CString sql= "select * from MEMBERUSER"; //查詢的SQL語句
try{
m_rec.CreateInstance(_uuidof(Recordset));//創建結果集對象
m_rec->Open(_bstr_t(sql),m_conn.GetInterfacePtr(),adOpenDynamic,adLockOptimistic,adCmdText);
}catch(_com_error e)
{
MessageBox(e.Description());
}
}
aa. ADO中Recordset.Open()參數說明
C.也可通過Execute函數來獲得結果集
//執行SQL語句
_RecordsetPtr CAdoDBDlg::AdoExucute(char* sqlStr)
{
try
{
if(m_conn==NULL)
{
MessageBox("請先連接數據庫,再操作!");
return NULL;
}
_variant_t RecordsAffected;//此次操作的記錄數
_RecordsetPtr PRecord;
//通過sql語句操作數據庫並返回結果集指針
PRecord=m_conn->Execute(_bstr_t(sqlStr),&RecordsAffected,adCmdText);
/*int IntRecords = RecordsAffected.intVal;
CString StrRecords="0";
StrRecords.Format("此次操作了 %d 條數據.",IntRecords);
AfxMessageBox(StrRecords);*/
return PRecord;
}
catch (_com_error e)
{
MessageBox(e.ErrorMessage());
}
}
D.關閉函數
//關閉數據庫連接
bool CAdoDBDlg::AdoClose()
{
if(m_conn!=NULL)
{
m_conn->Close();//關閉連接
m_conn=NULL;
m_rec->Close();//關閉結果集
m_rec=NULL;
//::CoUninitialize();//卸載COM環境
}
if(m_conn==NULL)
return TRUE;
else
return FALSE;
}
E.插入列表控件的表頭和設置樣式
我用的是CListCtrl控件來顯示查詢到的數據,因為之前做類似Windows任務管理器時就是用的列表控件來顯示數據,所以第一就想到了用它來顯示表中的數據。
//插入表頭
void CAdoDBDlg::InsertCol()
{ //表的列名
CString szItem[]={("記錄數"),_T("ID"),_T("MemberName"),_T("AccounterNumber"),_T("Age"),_T("Gender"),_T("Birthday"),_T("RoleName"),_T("Pwd"),_T("Integal")};
//設置列表控件的樣式
LONG lStyle;
lStyle= GetWindowLong(m_listCtrl.m_hWnd,GWL_STYLE);//獲得列表控件的當前樣式
lStyle &=~LVS_TYPEMASK; //清除顯示方式位
lStyle |=LVS_REPORT; //設置view屬性的值為Report
SetWindowLong(m_listCtrl.m_hWnd,GWL_STYLE,lStyle);
//設置擴展風格--網格
m_listCtrl.SetExtendedStyle(LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT);
//設置列表控件的表頭
int szLength = sizeof(szItem)/sizeof(szItem[0]);//求出數組長度
for (int i=0;i<szLength;i++)
{
m_listCtrl.InsertColumn(i,szItem[i],LVCFMT_RIGHT,70,-1);//向控件中插入表頭
}
}
aa.遍歷數據庫中的所有表名和表的所有字段 第 6.7點
5.///////////////////////////////////////////////增刪改查
a.查詢
void CAdoDBDlg::AdoQuery()
{
//查詢表中的數據
m_rec=AdoExucute("SELECT * FROM MEMBERUSER M;");
}
如果使用了GetRecordSet()方法這個函數可以不用,因為Recordset.Open(sql,.....)里面的sql語句就是查詢表數據,就可以得到結果集
b.增加數據
//增加數據
bool CAdoDBDlg::AdoAdd()
{
if(m_conn==NULL)
{
MessageBox("數據庫尚未連接,請連接后再操作!");
return FALSE;
}
CString strId1,strName,strAccounterName,strAge,strGender,strBirthday,strPwd,strIntegral,strRoleId;
int strId=12;
strName="中國人";
strAccounterName="zgr3";
strAge="100";
strGender="男";
//獲取系統當前時間
SYSTEMTIME st = {0};
GetLocalTime(&st);
strBirthday.Format("%d-%02d-%02d %02d:%02d:%02d",st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond);
strPwd="123456";
strIntegral="120";
strRoleId="2";
GetRecordSet();//獲取記錄集
if(m_rec!=NULL)
{
UpdateData(TRUE);
for(int i=0;i<3;i++)
{
strAccounterName.Format("lyx%d",i);//主鍵唯一,防止重復
m_rec->AddNew();
m_rec->PutCollect(_variant_t("MEMBERID"),_variant_t((long)(strId+i))); <span style="font-family: Arial, Helvetica, sans-serif;">//主鍵唯一,防止重復</span>
m_rec->PutCollect(_variant_t("MEMBERNAME"),_variant_t(strName));
m_rec->PutCollect(_variant_t("ACCOUNTNUMBER"),_variant_t(strAccounterName));
m_rec->PutCollect(_variant_t("AGE"),_variant_t(strAge));
m_rec->PutCollect(_variant_t("GENDER"),_variant_t(strGender));
m_rec->PutCollect(_variant_t("BIRTHDAY"),_variant_t(strBirthday));
m_rec->PutCollect(_variant_t("PWD"),_variant_t(strPwd));
m_rec->PutCollect(_variant_t("MEMBER_INTEGRAL"),_variant_t(strIntegral));
m_rec->PutCollect(_variant_t("ROLEID"),_variant_t(strRoleId));
}
m_rec->Update();
return TRUE;
}else
{
return FALSE;
}
}
注意:
1.如果主鍵沖突就無法增加數據到數據庫中,這個問題要注意,我就出現了這個問題,最后打斷點運行才發現。
2.如果你有的字段沒有插入,數據庫為空,那就查詢不出來,比如我因為生日日期類型之前沒有想到如何處理,就直接把
m_rec->PutCollect(_variant_t("BIRTHDAY"),_variant_t(strBirthday));這句注釋掉了,這樣雖然可以正常插入到數據庫中,但是當我點擊查詢按鈕時,在數據庫中這條數據及其以后的數據都無法在列表控件CListCtrl中顯示出來。
c.刪除數據
//刪除數據
bool CAdoDBDlg::AdoDelete()
{
if(m_conn==NULL)
{
MessageBox("數據庫尚未連接,請連接后再操作!");
return FALSE;
}
GetRecordSet();
int pos =m_listCtrl.GetSelectionMark();//獲得當前選中列表項索引,獲得第幾條數據
try
{
m_rec->Move(long(pos),vtMissing);//移到指定的第幾條數據
m_rec->Delete(adAffectCurrent);//刪除當前影響的數據
m_rec->Update();
return TRUE;
}
catch (_com_error e)
{
MessageBox(e.Description());
return FALSE;
}
}
D.修改數據
//修改
bool CAdoDBDlg::AdoUpdate()
{
if(m_conn==NULL)
{
MessageBox("數據庫尚未連接,請連接后再操作!");
return FALSE;
}
UpdateData(TRUE);
GetRecordSet();//獲取記錄集
int pos =m_listCtrl.GetSelectionMark();//獲得當前選中列表項索引
try{
m_rec->Move(long(pos),vtMissing);//移到指定條記錄
m_rec->PutCollect(_variant_t("gender"),_variant_t("女"));//修改指定字段的值
m_rec->Update();//更新到數據庫
return TRUE;
}catch(_com_error e)
{
MessageBox(e.Description());
return FALSE;
}
}
6.響應按鈕函數
//////////////////////////////////////按鈕處理函數
//建立連接
void CAdoDBDlg::OnBnClickedBtnAdolink()
{
// TODO: Add your control notification handler code here
if(m_conn==NULL)
{
////刪除列表控件中的所有記錄
int ColNum=m_listCtrl.GetHeaderCtrl()->GetItemCount();
for(int i=ColNum;i>=0;i--) //注意要從后面向前面刪除,從前往后刪會刪不干凈
{
m_listCtrl.DeleteColumn(i);
}
m_listCtrl.DeleteAllItems();//建立連接前刪除控件內的所有數據
////連接oracle數據庫的連接字符串
CString connStr="";
connStr.Format("Provider=OraOLEDB.Oracle.1;User ID=%s;Password=%s;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=(SERVICE_NAME=%s)));Persist Security Info=False",\
"XXX", "XXX", "127.0.0.1", "1521", "orcl");//User, Psw, Ip, Port, DataBaseName
<span style="white-space:pre"> </span>// 上文 \ 表示連接上一行
bool isConn=FALSE;
isConn=AdoOpen("XXX","XXX",(LPSTR)(LPCSTR)connStr,NULL);//建立連接
if(isConn)
{
MessageBox("連接oracle數據庫成功!");
////插入表頭
InsertCol();
}else
{
MessageBox("無法和數據庫建立連接!");
}
}
}
//斷開與數據庫的連接
void CAdoDBDlg::OnBnClickedBtnAdobreak()
{
// TODO: Add your control notification handler code here
if(AdoClose())
{
MessageBox("數據庫已斷開連接!");
}else{
MessageBox("數據庫斷開失敗!");
}
}
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//查詢數據庫
void CAdoDBDlg::OnBnClickedBtnQuery()
{
m_rec.CreateInstance(_uuidof(Recordset));//創建記錄實例
m_listCtrl.DeleteAllItems();//查詢前刪除控件內的所有數據
//先求出表中一共有多少條數據
_RecordsetPtr recordSet;
recordSet = AdoExucute("select count(*) from memberUser");
variant_t count=0;
_variant_t index=long(0);
count = recordSet->GetCollect(index);//獲得查詢到的結果中的值
int num = count.intVal;//轉換成int類型
// TODO: Add your control notification handler code here
//AdoQuery();//查詢數據
GetRecordSet();//獲取記錄集
int RecordNum=0;//計數
while (!m_rec->adoEOF)
{
variant_t id,name,accounterNumber,age,gender,birthday,roleName,pwd,integral;
for (int i=0;i<num;i++)
{
id= m_rec->GetCollect("memberId");
name = m_rec->GetCollect("MEMBERNAME");
accounterNumber=m_rec->GetCollect("ACCOUNTNUMBER");
age=m_rec->GetCollect("AGE");
gender=m_rec->GetCollect("GENDER");
birthday=m_rec->GetCollect("BIRTHDAY");
roleName=m_rec->GetCollect("ROLEID");
pwd=m_rec->GetCollect("PWD");
integral=m_rec->GetCollect("MEMBER_INTEGRAL");
CString strid,strname,straccounterNumber,strage,strgender,strbirthday,strroleName,strpwd,strintegral,strRecordNum;
strid=(LPCSTR)_bstr_t(id);
strname=(LPCSTR)_bstr_t(name);
straccounterNumber=(LPCSTR)_bstr_t(accounterNumber);
strage=(LPCSTR)_bstr_t(age);
strgender=(LPCSTR)_bstr_t(gender);
strbirthday=(LPCSTR)_bstr_t(birthday);
strroleName=(LPCSTR)_bstr_t(roleName);
strpwd=(LPCSTR)_bstr_t(pwd);
strintegral=(LPCSTR)_bstr_t(integral);
RecordNum++;
strRecordNum.Format("%d",RecordNum);
//插入數據
m_listCtrl.InsertItem(i,strRecordNum);
m_listCtrl.SetItemText(i,1,strid);
m_listCtrl.SetItemText(i,2,strname);
m_listCtrl.SetItemText(i,3,straccounterNumber);
m_listCtrl.SetItemText(i,4,strage);
m_listCtrl.SetItemText(i,5,strgender);
m_listCtrl.SetItemText(i,6,strbirthday);
m_listCtrl.SetItemText(i,7,strroleName);
m_listCtrl.SetItemText(i,8,strpwd);
m_listCtrl.SetItemText(i,9,strintegral);
m_rec->MoveNext();
}
}
//AdoClose();//關閉連接
}
//刪除
void CAdoDBDlg::OnBnClickedBtnDelete()
{
// TODO: Add your control notification handler code here
if(AdoDelete())
{
MessageBox("刪除成功!");
}else
{
MessageBox("刪除失敗!");
}
}
//增加
void CAdoDBDlg::OnBnClickedBtnAdd()
{
// TODO: Add your control notification handler code here
// CAddDataDlg m_AddDateDlg;
//if(m_AddDateDlg)
//m_AddDateDlg.DoModal();
if(AdoAdd())
{
MessageBox("增加成功!");
}else
{
MessageBox("增加失敗!");
}
}
//修改
void CAdoDBDlg::OnBnClickedBtnUpdate()
{
// TODO: Add your control notification handler code here
if(AdoUpdate())
{
MessageBox("更新成功!");
}else
{
MessageBox("更新失敗!");
}
}
7.效果界面

版權聲明:本文為博主原創文章,未經博主允許不得轉載。
