C++ 通過ADO連接Oracle數據庫


背景

接觸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()參數說明

bb.ADO中數據類型的介紹variant、BSTR

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.效果界面



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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM