一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

用VC++6.0開發(fā)多表聯(lián)接的數(shù)據(jù)庫(kù)應(yīng)用程序 - Visual C++ - Windows...

 陶情 2008-12-22
用VC++6.0開發(fā)多表聯(lián)接的數(shù)據(jù)庫(kù)應(yīng)用程序

本文介紹了用Visual C++6.0開發(fā)數(shù)據(jù)庫(kù)應(yīng)用程序時(shí),使用MFC ODBC類的編程方法,詳細(xì)說明了在MFC ODBC的派生類中設(shè)置SQL語(yǔ)句參數(shù)的方法,實(shí)現(xiàn)了二個(gè)表的關(guān)聯(lián)。

1.引言
開發(fā)Windows應(yīng)用程序時(shí),在很多情況下可能要和數(shù)據(jù)庫(kù)連接。數(shù)據(jù)庫(kù)類型多種多樣,功能結(jié)構(gòu)也各不相同。從比較簡(jiǎn)單的DBASE、FoxPro等到復(fù)雜的SYBASE、Qracle等大型數(shù)據(jù)庫(kù)系統(tǒng)。VC++6.0都提供了一些接口。程序員可利用這些接口方便地開發(fā)數(shù)據(jù)庫(kù)應(yīng)用程序。MFC ODBC類就是其中的一個(gè),在快速生成簡(jiǎn)單一致的接口應(yīng)用程序方面這些類非常有用。用戶不必了解ODBC API和SQL的具體細(xì)節(jié),利用ODBC類即可完成對(duì)數(shù)據(jù)庫(kù)的大部分操作。然而,VC++ Appwizard 生成的數(shù)據(jù)庫(kù)應(yīng)用程序,只是基于單個(gè)數(shù)據(jù)表的數(shù)據(jù)庫(kù)應(yīng)用程序。而實(shí)際應(yīng)用中,往往要求數(shù)據(jù)庫(kù)應(yīng)用程序能關(guān)聯(lián)二個(gè)或多個(gè)數(shù)據(jù)表。VC++的好多書籍對(duì)此只是簡(jiǎn)單的介紹。本文透徹地解決這一問題。
2.ODBC與MFC
2.1 ODBC
ODBC(開放數(shù)據(jù)庫(kù)互連)應(yīng)用程序可通過ODBCAPI訪問不同數(shù)據(jù)源中的數(shù)據(jù),每個(gè)不同的數(shù)據(jù)源類型由一個(gè)ODBC驅(qū)動(dòng)程序支持,這個(gè)驅(qū)動(dòng)程序完成了ODBC API程序的核心,并與具體的數(shù)據(jù)庫(kù)通信。ODBC環(huán)境提供了驅(qū)動(dòng)程序管理器(Driver Manager),管理那些與不同數(shù)據(jù)源連接的驅(qū)動(dòng)程序在ODBC32.DLL中執(zhí)行。應(yīng)用程序只需要與驅(qū)動(dòng)程序管理器連接,驅(qū)動(dòng)程序管理器就會(huì)根據(jù)應(yīng)用程序提供的數(shù)據(jù)源名,選擇正確的驅(qū)動(dòng)程序來訪問數(shù)據(jù)源。
要使用ODBC來開發(fā)數(shù)據(jù)庫(kù)應(yīng)用程序,必須使用在控制面板處的ODBC數(shù)據(jù)源管理器,來建立、配制數(shù)據(jù)源。應(yīng)本例應(yīng)用程序需要,按以下步驟建立所需的數(shù)據(jù)源。
1. 雙擊控制面板處的32位的ODBC程序,選擇對(duì)話框中的User DSN(用戶數(shù)據(jù)源名)選項(xiàng)卡。
2. 單擊Add按鈕,然后選擇一個(gè)數(shù)據(jù)源:Microsoft Visual FoxPro Driver。單擊“完成”,進(jìn)入下一步設(shè)置。
3. 在Data Source Name域內(nèi)輸入數(shù)據(jù)源名:DB-FSB。然后選擇Visual FoxPro數(shù)據(jù)庫(kù)的位置。
4. 單擊OK按鈕,返回到控制面板。
2.2 MFC ODBC
MFC的數(shù)據(jù)庫(kù)擴(kuò)展部分封裝了使用ODBC數(shù)據(jù)資源的細(xì)節(jié),提供了VC++與ODBC間一種簡(jiǎn)單的調(diào)用接口。MFC的ODBC類主要包括:用來與一個(gè)數(shù)據(jù)源相連的CDatabase類;用來處理從數(shù)據(jù)庫(kù)返回的一組記錄集的CRecordset類;簡(jiǎn)化從Crecordset對(duì)象中得到數(shù)據(jù)的顯示的CRecordView類。
雖然Cdatabase類允許你對(duì)一個(gè)數(shù)據(jù)庫(kù)執(zhí)行SQL語(yǔ)句,但是CRecordset類提供了應(yīng)用程序與數(shù)據(jù)交互的實(shí)質(zhì)。本例應(yīng)用程序使用CRecordset類來操作數(shù)據(jù)源.
CRecordset類的主要目的是讓應(yīng)用程序訪問從數(shù)據(jù)庫(kù)中返回的結(jié)果集。在應(yīng)用程序中要使用CRecordset類,可根據(jù)數(shù)據(jù)源并使用VC++中的ClassWizard來創(chuàng)建Crecordset派生類。通常,一個(gè)CRecordset派生類對(duì)應(yīng)用戶數(shù)據(jù)源中的一個(gè)表。每生成一個(gè)Crecordset派生類,就要選擇一個(gè)數(shù)據(jù)源和一個(gè)數(shù)據(jù)源中的一個(gè)表。若生成一個(gè)Crecordset派生類時(shí),選擇了一個(gè)數(shù)據(jù)源中的多個(gè)表,那么Crecordset派生類中的結(jié)果集是多個(gè)表的卡氏積(迪卡爾積)連接,顯然,在實(shí)際應(yīng)用中沒什么意義。應(yīng)用程序通過派生出的Crecordset類可對(duì)記錄集中的記錄進(jìn)行滾動(dòng)、修改、增加和刪除等操作。
CRecordView類具有幾個(gè)增強(qiáng)功能,允許使用對(duì)話框方式(DoDataExchange()函數(shù))直接從記錄集顯示數(shù)據(jù),使得從記錄集中顯示數(shù)據(jù)更為容易。并提供了記錄移動(dòng)等操作。
3. 多表聯(lián)接的數(shù)據(jù)庫(kù)應(yīng)用程序
3. 1本例程序功能:
通過FSB表的BZM字段及DBK1表的HH字段,將Visual FoxPro 的 FSB表與DBK1表(結(jié)構(gòu)如下)關(guān)聯(lián)起來。程序運(yùn)行出現(xiàn)界面如圖1。用鼠標(biāo)點(diǎn)擊工具條的?、?、(、(則FSB表記錄移動(dòng)而DBK1表的記錄沒移動(dòng)。用鼠標(biāo)點(diǎn)擊“關(guān)聯(lián)”按鈕,則DBK1表的記錄和FSB表記錄同步移動(dòng)(BZM編輯框內(nèi)容與HH編輯框內(nèi)容相同)。如果,要求按照具體的關(guān)鍵字值來查詢二個(gè)表中的相關(guān)記錄,那么,在“定位” 編輯框中輸入具體的關(guān)鍵字值,然后,用鼠標(biāo)點(diǎn)擊“關(guān)聯(lián)”按鈕,就會(huì)見到二個(gè)表在新的記錄集實(shí)現(xiàn)關(guān)聯(lián)。

表1: FSB表結(jié)構(gòu)
字段名
類型
備注
BZM
C
索引關(guān)鍵字
DGDL1
N

DGZD1
N

其它字段



表2: DBK1表
字段名
類型
備注
HH
C
索引關(guān)鍵字
BL
N

ZZCM
C

其它字段



基于MFC ODBC類開發(fā)的數(shù)據(jù)庫(kù)應(yīng)用程序,是通過MFC ODBC類使用SQL語(yǔ)句方式操縱數(shù)據(jù)表的。數(shù)據(jù)庫(kù)中表FSB與表DBK1關(guān)聯(lián)查詢的SQL語(yǔ)句是:
SELECT * FROM FSB,DBK1 WHERE FSB.BZM=DBK1.HH
由于創(chuàng)建一個(gè)CRecordset派生類時(shí),一般只選擇一個(gè)數(shù)據(jù)源中的一個(gè)表,因此基于MFC ODBC類開發(fā)的數(shù)據(jù)庫(kù)應(yīng)用程序要實(shí)現(xiàn)二個(gè)表關(guān)聯(lián),就要使用CRecordset類的參數(shù)m _strFilter。它相當(dāng)于SQL語(yǔ)句中的WHERE子句。參數(shù)m _strSort相當(dāng)于SQL語(yǔ)句中的GROUP BY子句。要注意m_strFilter字符串中不要包含“WHERE”關(guān)鍵字。本例在表FSB與表DBK1對(duì)應(yīng)的CRecordset派生類中分別使用了mbzm和mhh二個(gè)m _strFilter參數(shù)。用鼠標(biāo)點(diǎn)擊“關(guān)聯(lián)”按鈕時(shí),程序首先根據(jù)“定位” 編輯框中的內(nèi)容作為mbzm的值,在表FSB檢索結(jié)果集。表DBK1對(duì)應(yīng)的CRecordset派生類根據(jù)表FSB對(duì)應(yīng)的CRecordset派生類的當(dāng)前記錄m_bzm值,作為mhh的值實(shí)行檢索,從而得到與表FSB關(guān)鍵字段BZM對(duì)應(yīng)的表DBK1的記錄。實(shí)現(xiàn)了表FSB與表DBK1的關(guān)聯(lián)。由此可見,二表關(guān)聯(lián)的關(guān)鍵是m _strFilter參數(shù)的設(shè)置。

圖 1
3.2 數(shù)據(jù)庫(kù)應(yīng)用程序創(chuàng)建
3.2. 1 創(chuàng)建單表單文檔的數(shù)據(jù)庫(kù)應(yīng)用程序
根據(jù)前面建立的數(shù)據(jù)源DB-FSB,使用VC++ Appwizard 生成一個(gè)單表單、單文檔的數(shù)據(jù)庫(kù)應(yīng)用程序。選擇數(shù)據(jù)源DB-FSB的數(shù)據(jù)表時(shí)應(yīng)選擇FSB.DBF。應(yīng)用程序名為ZF0001(具體步驟可參考有關(guān)VC++資料)。ZF0001應(yīng)用程序中創(chuàng)建了CZf0001Doc、CZf0001Set、CZf0001View等派生類。
3.2.2 設(shè)置m _strFilter參數(shù)
在上一步生成的CZf0001Set類中,按以下方式,在① ② ③程序中設(shè)置m _strFilter參數(shù)(黑體部分的語(yǔ)句都是為CZf0001Set的參數(shù)mbzm而手動(dòng)增加的)。為節(jié)省篇幅,省略程序清單的部分內(nèi)容。
①. 在Crecordset派生類的定義中,描述了被連接的數(shù)據(jù)源表的字段,并在VC++ Appwizard 生成的程序注釋“// Field/Param Data ”中提示在此可定義參數(shù)。
CRecordset派生類:CZf0001Set的定義
class CZf0001Set : public Crecordset //Crecordset派生類CZf0001Set
{
public:
CZf0001Set(CDatabase* pDatabase = NULL);
DECLARE_DYNAMIC(CZf0001Set)
// Field/Param Data
//{{AFX_FIELD(CZf0001Set, CRecordset) //被綁定的字段
CString m_bzm;
CString m_dgqd1;
、、、、、、 //為節(jié)省篇幅,省略部分字段
CString m_bz;
//}}AFX_FIELD
CString mbzm; // 參數(shù)mbzm
// Overrides
// ClassWizard generated virtual function overrides
、、、、、、、
virtual void Dump(CDumpContext& dc) const;
#endif
};
②.Crecordset派生類:CZf0001Set的構(gòu)造函數(shù)
其中,對(duì)被綁定字段的相應(yīng)內(nèi)存變量進(jìn)行了初始化。
CZf0001Set::CZf0001Set(CDatabase* pdb) : CRecordset(pdb)
{
//{{AFX_FIELD_INIT(CZf0001Set)
m_bzm = _T("");
m_dgqd1 = _T("");
、、、、、、
m_bz = _T("");
m_nFields = 16; //數(shù)據(jù)源表的記錄字段個(gè)數(shù)
//}}AFX_FIELD_INIT
m_nDefaultType = snapshot;
m_nParams=1; // CZf0001Set的參數(shù)個(gè)數(shù)
mbzm=""; //參數(shù)初始化
}
③.記錄字段交換(RFX)
通過使用RFX,MFC框架可以在數(shù)據(jù)庫(kù)和CRecordset類變量之間交換。交換是通過執(zhí)行DoFieldExchange()函數(shù)而建立的。
void CZf0001Set:oFieldExchange(CFieldExchange* pFX)
{
//{{AFX_FIELD_MAP(CZf0001Set)
pFX->SetFieldType(CFieldExchange:utputColumn);
RFX_Text(pFX, _T("[bzm]"), m_bzm);
RFX_Text(pFX, _T("[dgqd1]"), m_dgqd1);
、、、、、、;
RFX_Text(pFX, _T("[dgdl2]"), m_dgdl2);
RFX_Text(pFX, _T("[bz]"), m_bz);
//}}AFX_FIELD_MAP
pFX->SetFieldType(CFieldExchange::param);
//把字段類型設(shè)為CFieldExchange::param
RFX_Text(pFX,"mbzm",mbzm); //為參數(shù)設(shè)置RFX 宏,如果有多個(gè)參數(shù),必須按SQL的語(yǔ)句中的位置標(biāo)志符的順序設(shè)置,RFX 宏中的參數(shù)的名字如"mbzm",并非用來與參數(shù)匹配,可以自己定義。
}
3.2.3 增加第二個(gè)表,并設(shè)置第二個(gè)表的參數(shù)
在3。2。1創(chuàng)建的數(shù)據(jù)庫(kù)應(yīng)用程序基礎(chǔ)上,進(jìn)入ClassWizard,點(diǎn)擊Add Class...按鈕并在彈出的菜單中選擇New...,然后在Create New Class對(duì)話框中的Name欄中輸入CZf1001,在Base class欄中選擇CRecordset,按Create按鈕。
在彈出的Database Options對(duì)話框中,在ODBC組合框里選擇DB-FSB數(shù)據(jù)源。然后按OK按鈕。在彈出的Select Database Tables對(duì)話框中選擇DBK1表。按OK確認(rèn)。并在所有存在 #include "CZf0001Set.h" 的文件中,都加入#include "CZf1001.h" 。這樣就創(chuàng)建了與DBK1表對(duì)應(yīng)的Crecordset派生類。
在第一步創(chuàng)建的CZf0001Doc類中,增加一個(gè)CZf1001 對(duì)象的指針變量m_zf1002(即:CZf1001* m_zf1002)。
按3.2.2介紹的CZf0001Set類m _strFilter參數(shù)的設(shè)置方法,在CZf1001類中,設(shè)置參數(shù)mhh。
3. 3 參數(shù)mhh及參數(shù)mbzm在CrecordView的派生類CZf0001View中的使用
3.3.1 參數(shù)在CZf0001View::OnInitialUpdate()函數(shù)使用
在CZf0001View::OnInitialUpdate()函數(shù)的開頭部分,調(diào)用CZf0001View:: GetDocument()從文檔類CZf0001Doc類中,返回二個(gè)CrecordSet類(CZf0001Set、CZf1001)的指針。根據(jù)返回的指針,設(shè)置m _strFilter (相當(dāng)于SQL語(yǔ)句的WHERE子句),并確定二個(gè)參數(shù)的初始值。這里要說明一點(diǎn):
m_pSet->m_strFilter="BZM like ?";
m_pSet2->m_strFilter="hh like ?";
語(yǔ)句中的“?”,在調(diào)用Open或Requery時(shí),“?"將分別自動(dòng)地被CZf0001Set::mbzm和 CZf1001::mhh的值取代。例如,指定mbzm為“31001",則m_pSet->m_strFilter將變成"BZM =31001"。這樣用戶只要指定了mbzm,就可以得到所需要的記錄集。CZf0001View::OnInitialUpdate()的程序清單如下(黑體部分的語(yǔ)句是手工增加的):
void CZf0001View::OnInitialUpdate()
{ m_pSet = &GetDocument()->m_zf0001Set;
m_pSet2=&GetDocument()->m_zf1002;
if(!m_pSet2->Open())
return;
m_pSet->m_strFilter="BZM like ?";
m_pSet->mbzm= "%"; //初始選擇所有記錄
m_pSet->m_strSort="";
m_pSet2->m_strFilter="hh like ?";
m_pSet2->mhh=m_pSet->m_bzm; //將表FSB對(duì)應(yīng)的CRecordset派生類的m_bzm的值,作為參數(shù)mhh的值 
m_pSet2->m_strSort="";  //檢索的結(jié)果不進(jìn)行排序
m_pSet->m_pDatabase= m_pSet2->m_pDatabase; //共享CDatabase

CRecordView::OnInitialUpdate();
GetParentFrame()->RecalcLayout();
ResizeParentToFit();
}
3.3.2 在對(duì)話框中加入編輯框
在資源視圖Dialog的IDD_ZF0001_FORM表單中,加入用戶需要的編輯框。用ClassWizard在第一個(gè)表FSB中選擇有關(guān)字段與它們相連。但是.使用ClassWizard無法找到第二個(gè)表DBK1字段變量,因此,對(duì)于計(jì)劃與第二個(gè)表DBK1字段相連的編輯框,必須用手工修改CRecordView類的DoDataExchange()(對(duì)話框數(shù)據(jù)交換函數(shù))。 在DoDataExchange()函數(shù) “//}}AFX_DATA_MAP” 后面加入有關(guān)內(nèi)容。見下面程序的黑體部分。如果黑體部分語(yǔ)句加在“//}}AFX_DATA_MAP”的前面,那么,要再次修改IDD_ZF0001_FORM表單時(shí),就無法使用ClassWizard.
void CZf0001View:oDataExchange(CDataExchange* pDX)
{
CRecordView:oDataExchange(pDX);
//{{AFX_DATA_MAP(CZf0001View)
DDX_Control(pDX, IDC_COMBO1, m_comb);
DDX_Control(pDX, IDC_EDIT4, m_SS);
DDX_FieldText(pDX, IDC_EDIT2, m_pSet->m_bl1, m_pSet);
DDX_FieldText(pDX, IDC_EDIT3, m_pSet->m_dgdl1, m_pSet);
DDX_FieldCBString(pDX, IDC_COMBO1, m_pSet->m_bzm, m_pSet);
DDX_FieldText(pDX, IDC_EDIT5, m_pSet->m_dgqd1, m_pSet);
//}}AFX_DATA_MAP
DDX_FieldText(pDX, IDC_EDIT1, m_pSet2->m_bl, m_pSet2);
DDX_FieldText(pDX, IDC_EDIT6, m_pSet2->m_hh, m_pSet2);
DDX_FieldText(pDX, IDC_EDIT7, m_pSet2->m_zzcm, m_pSet2);
}
3.3.3 在對(duì)話框中加入一個(gè)按鈕
為演示二個(gè)表關(guān)聯(lián)的效果,在對(duì)話框中加入一個(gè)“關(guān)聯(lián)”按鈕和一個(gè)輸入?yún)?shù)用的"定位"編輯框。并給此按鈕增加單擊事件代碼如下:

void CZf0001View::OnButton1()
{
// TODO: A

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    91播色在线免费播放| 日韩一区二区三区嘿嘿| 国产日韩精品欧美综合区| 国产亚洲欧美一区二区| 国产成人一区二区三区久久| 欧美精品一区二区三区白虎| 欧美精品亚洲精品一区| 精品精品国产自在久久高清| 国产又黄又爽又粗视频在线| 亚洲一区二区三区四区性色av| 亚洲视频一区二区久久久| 欧美国产日本高清在线| 91插插插外国一区二区| 欧美日韩一区二区综合| 日韩专区欧美中文字幕| 欧美精品久久一二三区| 日韩国产亚洲欧美激情| 久久福利视频在线观看| 日本一本在线免费福利| 一区二区三区日韩中文| 男人和女人黄 色大片| 久久久免费精品人妻一区二区三区| 91国内视频一区二区三区| 国产一区二区三区不卡| 精品国产丝袜一区二区| 国产精品色热综合在线| 日韩精品一区二区三区四区| 免费性欧美重口味黄色| 中文字幕亚洲精品乱码加勒比| 偷拍洗澡一区二区三区| 激情五月天免费在线观看| 国产精品超碰在线观看| 不卡一区二区高清视频| 精品女同在线一区二区| 国产精欧美一区二区三区久久| 日本理论片午夜在线观看| 精品少妇人妻av免费看| 午夜福利黄片免费观看| 高清不卡视频在线观看| 精品欧美国产一二三区| 自拍偷拍一区二区三区|