下圖是程序的最終效果,包含了數據的顯示,添加,修改,刪除這幾項數據庫操作的常用功能。
我的調試環境是xp,mysql版本是mysql4.0.23
1.安裝Mysql的ODBC驅動
從http://www.mysql.com上下載驅動程序
地址:http://dev.mysql.com/downloads/connector/odbc/3.51.html#win32
我是下載的Windows ZIP/Setup.EXE
下載到本機之後從zip包中解壓出setup.exe文件,雙擊安裝,沒什麼可說的,完全的傻瓜式安裝
2.設置ODBC數據源
配置MySQL的ODBC數據源有兩種方法
第一種:手工設置
比較麻煩,但是確是比較安全的辦法。
步驟如下:
開始 -> 控制面板 -> 管理工具 -> 數據源 (ODBC),雙擊數據源(ODBC)之後會出來如下的界面
點擊右上角的"添加"按鈕之後會出現如下的界面
可以看到,我們剛才安裝的驅動程序已經出現在列表中了,選中它,然後單擊完成,此時會出來下面的界面
按上圖所示,填寫好各項連接所需要的信息點擊“Test”可以進行測試,如果出現sucessful字樣就表示成功了
我解釋一下填寫的信息:Data Source Name:縮寫就是DSN,中文翻譯過來就是數據源名稱,就是給數據源取個名,為了安全還是取英文名吧,省得出現意外。
Description:描述,可填可不填,我比較懶,就沒填,想填也行,就是描述一下這個數據源是哪家的,干啥用的等等,隨便吧Server:服務器,不能省,我填的是localhost,如果你有遠程主機,不妨試試填上遠程主機的IP地址,我沒試過,不清楚User:用戶名,我本地數據庫用的是root,你們如果有別的就根據自己的情況填吧Password:密碼,我沒設置密碼,有則填之,沒有就留空Database:數據庫,這是一個listbox,可以自己填,也可以從下拉列表中選,如果你前面的Server,User,Password都正確的話,下拉列表中會出來可選的數據庫,這個就是我們要連接的數據庫資源。
解釋完畢,點了OK之後,我們就算設置完成了。
第二種:動態設置這種辦法是指在程序執行時才添加數據源,SQLConfigDataSource是所用的方法,查msdn可以查到它的用法第一個參數一般設置成NULL就可以了,第二個參數我用的是ODBC_ADD_DSN,表示是新增數據源第三個參數是驅動的名稱,在數據源(ODBC)中抄過來就OK了第四個參數是連接字符串,多個參數用分隔開,DSN就是數據源名稱,UID是用戶名,PWD是密碼,SERVER是主機名,DATABASE是數據庫名稱,最後用兩個結束。
只要在程序中加上這一行,當程序執行到它時,就會在數據源中加上你所設置的數據源,並且可以在控制面板 -> 管理工具 -> 數據源(ODBC)中查到。如圖二所示,裡面的odbctest和odbctestqqqq,前者就是動態創建的,後者是最初手工創建的。
SQLConfigDataSource(NULL,ODBC_ADD_DSN,"MySQL ODBC 3.51 Driver","DSN=odbctest UID=root PWD= SERVER=localhost DATABASE=odbc");
3.編寫連接程序我用的是VC6.0,VC這東西好是好,就是封裝得太多了,像我等這樣初來乍到之人一時半會是狗咬烏龜——找不到下口的地方下面我就按我的方式來說說,肯定有高手有更高明的辦法,不妨評論一二,也好讓我等開開眼界。
(1)。創建一個基於對話框的工程在VC中點擊菜單中 File -> New,在Projects的下拉菜單中選擇MFC AppWizard (exe);在右上角的輸入框中填寫一個工程的名字,我取名叫ODBCTest;選擇一個存放目錄,我的是存在E:cODBCTest;點擊OK進入下一步,選擇基於對話框,然後點finish完成設置。
(2)。包含頭文件切換到file view,在header files中找到stdafx.h,這是MFC第一個要包含的頭文件,我們在裡面加上如下兩行,將odbc及數據庫操作所需的頭文件引入到工程中。沒這兩個頭文件編譯時會出錯。
……
#include <odbcinst.h> #include "afxdb.h"// 用的時候把引號換成尖括號,編輯器自動給轉成了非源碼形式,郁悶
//{{AFX_INSERT_LOCATION}}……
(3)。畫主體對話框
主體對話框是用來列表顯示數據,並放置其他操作入口的界面,在這個程序中,我們的主體對話框上會放置一個列表控件和五個按鈕控件。
在資源視圖上選擇對話框資源,然後繪制如下圖如示的對話框
對圖上的控件作一下說明
1)。列表,用的是list control,注意在styles中的view要設置成report(報表),如下圖
2)。依次添加了三個按鈕,添加,修改,刪除。
在這裡做下說明,一般看網上的教程或是書,上面講的程序的編寫過程都是按步就班,沒有多余的過程,因為作者都已經重新做了排版和設計工作,力求簡潔。但實際編程中確是不一樣的,常常要經過多次修改,重排,優化,所以這裡我打算按實際程序的編寫過程來說明,而不是按步就班的說明,力求還原程序編寫的全過程。作為一個初學VC的新手,相信有很多跟我一樣的新手也會遇到同樣的困難,沒關系,萬事開頭難。
一般的教程講到這裡就可能會去將後面所要用到的資源准備好,然後進行“系統的”編程。我這裡不這樣走,而是回到主窗口的編程上來,一個功能一個功能的實現。
1)。實現數據的列表顯示暈了,很多人肯定會暈了。這不扯淡嗎,我們的數據庫(庫名叫:odbc)裡啥東西都還沒有,顯示啥呀。
沒關系,好在俺也搞過Mysql幾年,別的不會,管理Mysql的工具倒是知道不少,比如:EMS,phpMyAdmin,DBtools……
我為了簡單就用了phpMyadmin這個工具,這個工具需要在本地安裝了php和mysql才能使用,如果本地沒有裝php就用不了了,不過沒關系,去下載一個EMS也不錯,非常強大的工具,華麗的界面,豐富的功能。用過SQL server的可能更習慣於使用DBTools Manager,這也是個強大的工具,值得一試。
二毛說,學VC,在還沒有入門之前機器上就會有一堆的工具。初始還不信,現在我信了,這不,剛學沒幾天,機器上就跑上了VC,msdn,另外還有一堆的入門電子書,閱讀器,視頻播放軟件……既然已經有這麼多了,再多幾個也無所謂了。
跑題了哈,我先剎車倒回來,接著講數據的顯示,第一步:在odbc庫中建一張表list,都怪我,這庫名取得有點誤導觀眾,這裡再次申明一下,這裡的odbc是我建的一個MySQL數據庫,不是那個該死的縮寫。下面是建好之後的表
id:是一個自增,非負的10位整型字段,用來存放用戶的ID
name:是一個40位變長的字符串,用來存放用戶名
age:是一個3位的小整型字段,因為沒有啟用非負設置,最大可以到127,此字段存放用戶年齡
這就是list表的結構,然後我們在表中插入幾條初始數據,用來顯示。
phpMyAdmin的使用我就不多說了,這屬於工具的使用,不在本文的說明范圍之內。
添加好數據之後,我們可以在phpmyadmin中浏覽到它們,如下圖:
2)。編程顯示數據列表
回到VC中來,在類視圖中,找到CODBCTestDlg並展開,找到裡面的OnInitDialog()方法,此方法是對話框的初始化方法,我的最初想法就是在這裡面完成數據庫的連接,查詢,並輸出數據到列表中。於是我寫了如下的代碼
CDatabase db;
db.Open(NULL,FALSE,FALSE,"ODBC;DSN=odbctest;UID=root;PWD=");
CRecordset rs( &db );
rs.Open( CRecordset::forwardOnly, _T("SELECT * FROM list order by id Asc"));
short nFields = rs.GetODBCFieldCount();
while(!rs.IsEOF())
{
CString varID;
rs.GetFieldValue("id", varID);
m_list.InsertItem(0,varID);
CString varName;
rs.GetFieldValue("name", varName);
m_list.SetItemText(0, 1, varName);
CString varAge;
rs.GetFieldValue("age", varAge);
m_list.SetItemText(0, 2, varAge);
rs.MoveNext();
}
rs.Close();
db.Close();
但後來發現有問題,因為在後面每添加一條記錄之後都需要更新列表,重新輸出,這就需要再次寫一段跟上面一模一樣的代碼,我靠,這不浪費時間嗎。於是,我將上面的這段代碼放到了類的一個方法中。步驟如下:
1)。在類視圖中選中CODBCTestDlg,點右建,選擇新增function,然後創建一個void GetRecord()的方法,如下圖
2)。將上面的代碼放到方法中,最終的代碼如下
void CODBCTestDlg::GetRecord()
{
m_list.DeleteAllItems();
CDatabase db;
db.Open(NULL,FALSE,FALSE,"ODBC;DSN=odbctest;UID=root;PWD=");
CRecordset rs( &db );
rs.Open( CRecordset::forwardOnly, _T("SELECT * FROM list order by id Asc"));
//short nFields = rs.GetODBCFieldCount();// 此行原是用來遍歷表中字段,現在沒有用上
while(!rs.IsEOF())
{
CString varID;
rs.GetFieldValue("id", varID);
m_list.InsertItem(0,varID);
CString varName;
rs.GetFieldValue("name", varName);
m_list.SetItemText(0, 1, varName);
CString varAge;
rs.GetFieldValue("age", varAge);
m_list.SetItemText(0, 2, varAge);
rs.MoveNext();
}
rs.Close();
db.Close();
m_list.AdjustColumnWidth();//新增了一個CMyListCtrl類,這是裡面我新增的一個方法,用來自適應數據寬度
}
這樣,以後在需要重新取列表數據時就可以調用此方法了,這就叫重用。
ODBC連接數據庫,有兩個類是需要關心的,第一個是CDatabase,另一個是CRecordset
前者用於數據庫連接的建立,後者用於數據集的取得
建立連接,用如下的代碼來實現
CDatabase db;//聲明一個對象
db.Open(NULL,FALSE,FALSE,"ODBC;DSN=odbctest;UID=root;PWD=");// 連接數據源
至於為什麼這麼寫,查msdn吧
取數據集合
CRecordset rs( &db );// 綁定數據源
rs.Open( CRecordset::forwardOnly, _T("SELECT * FROM list order by id Asc"));//查詢數據
要執行sql,我並沒有用ODBC提供的方法,而是用更直接的辦法
CString sql;
sql.Format("update list set name='%s', age='%s' where id=%d",str_name, str_age, item_id);
db.ExecuteSQL(sql);
這種辦法的好處是可以不用從CRecordSet繼承新類,且對我這樣了解一部分sql的新手比較直觀。