近期寫一個數據庫的課程設計,用的是C++ MFC 。最開始用的是ADO技術,但是苦於網上大部分的教程都是VC6.0的,對着教程敲了4,5遍仍是執行不成功。我用的IDE是VS2012,畢竟VC6.0和VS2012之間的差距太大了,因此就改爲了ODBC編程,實際上ODBC對於數據庫類的操做封裝的很是好,可以很是方便的使用相關的函數而且不需要本身去寫一些異常處理機制,對於新手來講是很是方便的,網上也有很是多的ODBC教程,我照着網上的VS2010的ODBC教程而後加上本身的理解寫了一個學生成績管理系統,很是easy,但是也基本上能把ODBC的思想和簡單的使用方法說清楚了,聲明:此文章僅適合剛剛接觸數據庫的新手以及相關專業的大學生,大神就可以直接忽略了,若有大神看了文章後對代碼或者思想提出寶貴的改進意見,在下不勝感激!sql
OK,廢話很少說。首先打開VS2012->創建一個MFC應用程序(基於DIALOG),而後就是本身拉EDIT和BUTTON了,這個很是easy,基本學過一點MFC的都曉得怎麼去弄,大小間距什麼的就不具體介紹了,VS2012->格式,裏面有對齊和使大小一樣,本身去弄就可以了,基本上4個static,4個EDIT,四個BUTTON,一個List Control,注意的是List Control的格式設置爲report。
數據庫
這個就是個人基本界面,cno是課程號,cname是課程名,xf是學分,因爲數據庫中就是這麼寫的,因此static裏面的就不變了,這個可以本身隨便寫,沒有影響的。編程
如下就是基本的了,首先要作的就是加入成員變量,在主對話框右鍵單擊->類嚮導->成員變量,而後就是本身加入成員,這裏要注意的是類型,這個類型爲何要這麼寫,下文我會一一說明
函數
這些基礎工做都作好以後,接下來就是加入ODBC使用者了,這裏的ODBC使用者的加入也很是easy,類嚮導->加入類->MFC ODBC使用者
而後PV數據源,點擊機器數據源
要注意的是這裏的數據源是需要本身去配置的,具體的配置方法這裏就不具體介紹了,百度上隨便搜一下都有好多,也很是easy,基本上3分鐘就能配置好,我這裏用的數據源已是配置好的了,叫
Test,配置好數據源以後就會生成一個類,這個類的名字就是SQL 2008裏面列的名字,比方我這裏就是CKC,因爲個人數據庫中的列就是KC。如下咱們來看下這個類裏面有什麼內容。如下是.h文件的一些內容。
CString
m_cno;
CString
m_cname;
long
m_xf;
// 重寫
// 嚮導生成的虛函數重寫
public:
virtual CString GetDefaultConnect();
// 默認鏈接字符串
virtual CString GetDefaultSQL();
// 記錄集的默認 SQL
virtual void DoFieldExchange(CFieldExchange* pFX);
// RFX 支持
// 實現
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
這是基本的代碼,當中最重要的的m_cno,m_cname,m_xf當中m_cno,m_cname是CStringA類型的,僅僅只是我把它改爲了CString,CStringA是和UNICODE有關的,這裏咱們臨時不需要考慮編碼的問題,因此直接改爲CString。
這就是爲何剛剛加入的成員變量的類型是CString,CString,long,要和這個類裏面的類型同樣。
再來看看.cpp文件的一些內容,比較重要的是
m_cno = "";
m_cname = "";
m_xf = 0;
m_nFields = 3;
m_nDefaultType = dynaset;
這個是類生成初始化的結果,GetDefaultConnect()這個函數返回的是鏈接字符串,裏面包含DSN,UID,PSW等等,本身可以去看看,因爲包含了賬號和password,這裏我就不貼出來了,其它的都沒什麼。OK,現在咱們正式開始實現對數據庫的操做,在MFC界面上雙擊查詢BUTTON,這時候咱們就會進代碼界面了。
開始,咱們要作的是對List Control進行初始化,廢話很少說,上代碼。
首先,需要本身寫一個初始化函數,這個函數是BOOL CXSKC::OnInitDialog(),實際上這個函數應該是在生成dlg時候就有的,但是不曉得爲何我生成的時候沒有,很是愚蒙,多是以前的步驟弄錯了,但是這不影響,假設有的就直接在函數裏面寫,假設沒有就本身加一個函數進去,很是easy吧。
函數裏面的內容是
UpdateData(FALSE);
MyCjList.SetExtendedStyle(LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_TWOCLICKACTIVATE);
MyCjList.InsertColumn(0,L"xf",LVCFMT_CENTER,80,0);
MyCjList.InsertColumn(0,L"cname",LVCFMT_CENTER,160,0);
MyCjList.InsertColumn(0,L"cno",LVCFMT_CENTER,80,0);
return TRUE;
這個是對List Control的一些初始化,詳細含義很是easy,隨便查一查都知道,沒什麼好說的。
而後找到DoDataExchange()函數,在函數裏面加上這些代碼CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_LIST1, MyCjList);
DDX_Text(pDX, IDC_EDIT1, MyCno);
DDX_Text(pDX, IDC_EDIT2, MyCname);
DDX_Text(pDX, IDC_EDIT3, MyXf);
GetDlgItem(IDC_EDIT3)->SetWindowTextW(L"");
這個也沒什麼好說的,都很是easy。現在,List Control就初始化好了,接下來就是重中之重了,查詢的實現。SQL 中的查詢語句是select * from KC where cno =。。。,因爲cno是主鍵,爲了簡潔,咱們就僅僅用主鍵查詢就可以了。
void CXSKC::OnBnClickedButton1()//這個就是查詢button的代碼
{
// TODO: 在此加入控件通知處理程序代碼
CKC MyKC;//XS類操做對象
MyKC.Open();
MyKC.MoveFirst();
CString str1,str2,str3;
GetDlgItem(IDC_EDIT1)->GetWindowTextW(str1);
GetDlgItem(IDC_EDIT2)->GetWindowTextW(str2);
GetDlgItem(IDC_EDIT3)->GetWindowTextW(str3);
CString sql;
sql.Format(L"select * from KC where cno = '%s'",str1);
MessageBox(sql);
ListAll(sql);
}
我解釋一下,要操做數據庫,首先要作的就是打開數據庫,
CKC定義一個對象,調用open()函數,打開數據庫以後把EDIT裏面的內容給str,
三個EDIT相應三個str,注意順序不要錯了,否則就悲劇了。而後,需要調用一個movefirst()函數,移動到第一個記錄,這樣就可以從頭至尾順序的掃描表了(大概的過程就這樣),畢竟不是專業的數據庫project師,對於數據庫的深刻理解還不夠。。。而後就是sql語句了,CString 建立一個對象,用來存放sql語句
,Format()函數真是一個好東西,我太喜歡這個函數了,它可以把後面str的內容插入‘%’,簡直就是神器啊!s說明的是一個字符串,還有u,等等,有興趣的可以本身去了解一下。MessageBox()是我用來測試SQL語句對不正確的,ListAll()函數是需要本身寫的,如下是ListAll()函數的代碼。
void CXSKC::ListAll(CString str)
{
MyCjList.DeleteAllItems();
MyCjList.InsertItem(0,L"");
CKC m_kc;//類的對象,用來調用操做數據庫函數
try
{
if(m_kc.IsOpen())
{
m_kc.Close();
}
if(!m_kc.Open(CRecordset::snapshot,str))
{
MessageBox(L"數據庫打開失敗",L"數據錯誤",MB_OK);
return;
}
}
catch(CDBException *e)
{
e->ReportError();
}
int index = 0;
//int line = 0;
CString t;
m_kc.MoveFirst();
while(!m_kc.IsEOF())
{
//MessageBox(L"123");
MyCjList.SetItemText(index,0,m_kc.m_cno);
m_kc.m_cname.Remove(' ');
MyCjList.SetItemText(index,1,m_kc.m_cname);
//MessageBox(m_xs.m_name);
t.Format(L"%Id",m_kc.m_xf);
const TCHAR * ip = (LPCTSTR)t;
MyCjList.SetItemText(index,2,t);
m_kc.MoveNext();
index++;
}
m_kc.Close();
}
說明一下,t.Format(L"%Id",m_kc.m_xf);
const TCHAR * ip = (LPCTSTR)t;
MyCjList.SetItemText(index,2,t);
這兩句是一個簡單的類型轉換,設計到LPCTSTR類型,因此有些麻煩。
這樣就寫好了查詢BUTTONbutton了,接下來就是加入,刪除和改動了,詳細的思想都差點兒相同,假設查詢能搞清楚,那麼其它的應該很是easy就寫出來,如下我把代碼貼上來。
oid CXSKC::OnBnClickedButton2()//加入
{
// TODO: 在此加入控件通知處理程序代碼
CString str1,str2,str3;
GetDlgItem(IDC_EDIT1)->GetWindowTextW(str1);
GetDlgItem(IDC_EDIT2)->GetWindowTextW(str2);
GetDlgItem(IDC_EDIT3)->GetWindowTextW(str3);
CString sql;//sql語句
CDatabase m_xs;//對象
m_xs.Open(L"Test",FALSE,FALSE,L"ODBC;UID=;PWD=;");
try{
if(str1.IsEmpty()||str2.IsEmpty()||str3.IsEmpty())
{
MessageBox(L"輸入的信息不無缺請無缺後在插入數據",L"提示");
MyCno = (L"");
MyCname = L"";
MyXf = _ttoi(L"");
UpdateData(FALSE);
}
else
{
sql.Format(_T("insert into KC values('%s','%s','%s')"),str1,str2,str3);
MessageBox(sql);
m_xs.ExecuteSQL(sql);
MessageBox(L"加入成功!",L"提示");
//UpdateData(FALSE);
}
}
catch(CDBException ex)
{
MessageBox(L"插入異常");
ex.ReportError();
ex.Delete();
}
m_xs.Close();
}
void CXSKC::OnBnClickedButton3()//刪除
{
// TODO: 在此加入控件通知處理程序代碼
CString str1,str2,str3;
GetDlgItem(IDC_EDIT1)->GetWindowTextW(str1);
GetDlgItem(IDC_EDIT2)->GetWindowTextW(str2);
GetDlgItem(IDC_EDIT3)->GetWindowTextW(str3);
CString sql;//sql語句
CDatabase m_xs;//對象
m_xs.Open(L"Test",FALSE,FALSE,L"ODBC;UID=;PWD=");//
賬號與password我就不寫了,本身把本身的SQL的賬號與password寫上就好。
sql.Format(L"delete from KC where cno = '%s'",str1);
try{
if(str1.IsEmpty())
{
MessageBox(L"信息不完整",L"提示");
UpdateData(FALSE);
return;
}
else
{
//sql.Format(L"delete from KC where cno = '%S'",str1);
MessageBox(sql);
m_xs.ExecuteSQL(sql);
MessageBox(L"刪除成功!",L"提示");
}
}
catch(CDBException ex)
{
ex.ReportError();
ex.Delete();
}
m_xs.Close();
}
void CXSKC::OnBnClickedButton4()//改動
{
// TODO: 在此加入控件通知處理程序代碼
CString str1,str2,str3;
GetDlgItem(IDC_EDIT1)->GetWindowTextW(str1);
GetDlgItem(IDC_EDIT2)->GetWindowTextW(str2);
GetDlgItem(IDC_EDIT3)->GetWindowTextW(str3);
CString sql;//sql語句
CDatabase m_xs;//對象
m_xs.Open(L"Test",FALSE,FALSE,L"ODBC;UID=;PWD=;");
sql.Format(L"update KC set cno = '%s' , cname = '%s',xf = '%s' where cno = '%s'",str1,str2,str3,str1);
try
{
if(str1.IsEmpty()||str2.IsEmpty()||str3.IsEmpty())
{
MessageBox(L"信息輸入不完整",L"提示");
UpdateData(FALSE);
return;
}
else
{
sql.Format(L"update KC set cno = '%s' , cname = '%s',xf = '%s' where cno = '%s'",str1,str2,str3,str1);
MessageBox(sql);
if(MessageBox(L"cno:"+str1+'\n'+L"cname:"+str2+'\n'+L"xf:"+str3+'\n',L"確認改動?",MB_OKCANCEL)==IDCANCEL)
{
return;
}
else
{
m_xs.ExecuteSQL(sql);
MessageBox(L"改動成功",L"提示");
}
}
}
catch(CDBException ex)
{
ex.ReportError();
ex.Delete();
}
m_xs.Close();
}
這些代碼都很是easy,用CDataBase類生成一個對象,這個對象來調用ExecuteSQL(),這個函數可以運行SQL語句。
而後就是異常處理機制,這些就不詳細多說了。
注意的是:1.
每調用一次open()都要調用一次close();不要忘記了,否則會出現沒法操做數據庫的狀況,切記切記!
2.記得#include 「afxdb.h"。僅僅有include了這個頭文件以後才幹用CDataBase。
剩下的就沒什麼好說的,主要的就是這樣,假設你們還有什麼意見和建議或者發現了文章有什麼寫的不對的地方歡迎指正~!
賣個萌
![可憐](http://static.javashuo.com/static/loading.gif)
哈哈~!感謝閱讀!