用vc++6.0开发多表联接的数据库应用程序.htm

来自「用VC++6.0开发多表联接的数据库应用程序」· HTM 代码 · 共 811 行 · 第 1/4 页

HTM
811
字号
                  Name域内输入数据源名:DB-FSB。然后选择Visual FoxPro数据库的位置。 <BR>4. 
                  单击OK按钮,返回到控制面板。 <BR>2.2 MFC ODBC 
                  <BR>MFC的数据库扩展部分封装了使用ODBC数据资源的细节,提供了VC++与ODBC间一种简单的调用接口。MFC的ODBC类主要包括:用来与一个数据源相连的CDatabase类;用来处理从数据库返回的一组记录集的CRecordset类;简化从Crecordset对象中得到数据的显示的CRecordView类。 
                  <BR>虽然Cdatabase类允许你对一个数据库执行SQL语句,但是CRecordset类提供了应用程序与数据交互的实质。本例应用程序使用CRecordset类来操作数据源. 
                  <BR>CRecordset类的主要目的是让应用程序访问从数据库中返回的结果集。在应用程序中要使用CRecordset类,可根据数据源并使用VC++中的ClassWizard来创建Crecordset派生类。通常,一个CRecordset派生类对应用户数据源中的一个表。每生成一个Crecordset派生类,就要选择一个数据源和一个数据源中的一个表。若生成一个Crecordset派生类时,选择了一个数据源中的多个表,那么Crecordset派生类中的结果集是多个表的卡氏积(迪卡尔积)连接,显然,在实际应用中没什么意义。应用程序通过派生出的Crecordset类可对记录集中的记录进行滚动、修改、增加和删除等操作。 
                  <BR>CRecordView类具有几个增强功能,允许使用对话框方式(DoDataExchange()函数)直接从记录集显示数据,使得从记录集中显示数据更为容易。并提供了记录移动等操作。 
                  <BR>3. 多表联接的数据库应用程序 <BR>3. 1本例程序功能: 
                  <BR>通过FSB表的BZM字段及DBK1表的HH字段,将Visual FoxPro 的 
                  FSB表与DBK1表(结构如下)关联起来。程序运行出现界面如图1。用鼠标点击工具条的?、?、(、(则FSB表记录移动而DBK1表的记录没移动。用鼠标点击“关联”按钮,则DBK1表的记录和FSB表记录同步移动(BZM编辑框内容与HH编辑框内容相同)。如果,要求按照具体的关键字值来查询二个表中的相关记录,那么,在“定位” 
                  编辑框中输入具体的关键字值,然后,用鼠标点击“关联”按钮,就会见到二个表在新的记录集实现关联。 <BR><BR>表1: 
                  FSB表结构 <BR>字段名 <BR>类型 <BR>备注 <BR>BZM <BR>C <BR>索引关键字 <BR>DGDL1 
                  <BR>N <BR><BR>DGZD1 <BR>N <BR><BR>其它字段 <BR><BR><BR><BR>表2: 
                  DBK1表 <BR>字段名 <BR>类型 <BR>备注 <BR>HH <BR>C <BR>索引关键字 <BR>BL 
                  <BR>N <BR><BR>ZZCM <BR>C <BR><BR>其它字段 <BR><BR><BR><BR>基于MFC 
                  ODBC类开发的数据库应用程序,是通过MFC 
                  ODBC类使用SQL语句方式操纵数据表的。数据库中表FSB与表DBK1关联查询的SQL语句是: <BR>SELECT * 
                  FROM FSB,DBK1 WHERE FSB.BZM=DBK1.HH 
                  <BR>由于创建一个CRecordset派生类时,一般只选择一个数据源中的一个表,因此基于MFC 
                  ODBC类开发的数据库应用程序要实现二个表关联,就要使用CRecordset类的参数m 
                  _strFilter。它相当于SQL语句中的WHERE子句。参数m _strSort相当于SQL语句中的GROUP 
                  BY子句。要注意m_strFilter字符串中不要包含“WHERE”关键字。本例在表FSB与表DBK1对应的CRecordset派生类中分别使用了mbzm和mhh二个m 
                  _strFilter参数。用鼠标点击“关联”按钮时,程序首先根据“定位” 
                  编辑框中的内容作为mbzm的值,在表FSB检索结果集。表DBK1对应的CRecordset派生类根据表FSB对应的CRecordset派生类的当前记录m_bzm值,作为mhh的值实行检索,从而得到与表FSB关键字段BZM对应的表DBK1的记录。实现了表FSB与表DBK1的关联。由此可见,二表关联的关键是m 
                  _strFilter参数的设置。 <BR><BR>图 1 <BR>3.2 数据库应用程序创建 <BR>3.2. 1 
                  创建单表单文档的数据库应用程序 <BR>根据前面建立的数据源DB-FSB,使用VC++ Appwizard 
                  生成一个单表单、单文档的数据库应用程序。选择数据源DB-FSB的数据表时应选择FSB.DBF。应用程序名为ZF0001(具体步骤可参考有关VC++资料)。ZF0001应用程序中创建了CZf0001Doc、CZf0001Set、CZf0001View等派生类。 
                  <BR>3.2.2 设置m _strFilter参数 <BR>在上一步生成的CZf0001Set类中,按以下方式,在① ② 
                  ③程序中设置m 
                  _strFilter参数(黑体部分的语句都是为CZf0001Set的参数mbzm而手动增加的)。为节省篇幅,省略程序清单的部分内容。 
                  <BR>①. 在Crecordset派生类的定义中,描述了被连接的数据源表的字段,并在VC++ Appwizard 
                  生成的程序注释“// Field/Param Data ”中提示在此可定义参数。 
                  <BR>CRecordset派生类:CZf0001Set的定义 <BR>class CZf0001Set : public 
                  Crecordset //Crecordset派生类CZf0001Set <BR>{ <BR>public: 
                  <BR>CZf0001Set(CDatabase* pDatabase = NULL); 
                  <BR>DECLARE_DYNAMIC(CZf0001Set) <BR>// Field/Param Data 
                  <BR>//{{AFX_FIELD(CZf0001Set, CRecordset) //被绑定的字段 <BR>CString 
                  m_bzm; <BR>CString m_dgqd1; <BR>、、、、、、 //为节省篇幅,省略部分字段 
                  <BR>CString m_bz; <BR>//}}AFX_FIELD <BR>CString mbzm; // 
                  参数mbzm <BR>// Overrides <BR>// ClassWizard generated virtual 
                  function overrides <BR>、、、、、、、 <BR>virtual void 
                  Dump(CDumpContext&amp; dc) const; <BR>#endif <BR>}; 
                  <BR>②.Crecordset派生类:CZf0001Set的构造函数 
                  <BR>其中,对被绑定字段的相应内存变量进行了初始化。 
                  <BR>CZf0001Set::CZf0001Set(CDatabase* pdb) : CRecordset(pdb) 
                  <BR>{ <BR>//{{AFX_FIELD_INIT(CZf0001Set) <BR>m_bzm = _T(""); 
                  <BR>m_dgqd1 = _T(""); <BR>、、、、、、 <BR>m_bz = _T(""); 
                  <BR>m_nFields = 16; //数据源表的记录字段个数 <BR>//}}AFX_FIELD_INIT 
                  <BR>m_nDefaultType = snapshot; <BR>m_nParams=1; // 
                  CZf0001Set的参数个数 <BR>mbzm=""; //参数初始化 <BR>} <BR>③.记录字段交换(RFX) 
                  <BR>通过使用RFX,MFC框架可以在数据库和CRecordset类变量之间交换。交换是通过执行DoFieldExchange()函数而建立的。 
                  <BR>void CZf0001Set::DoFieldExchange(CFieldExchange* pFX) 
                  <BR>{ <BR>//{{AFX_FIELD_MAP(CZf0001Set) 
                  <BR>pFX-&gt;SetFieldType(CFieldExchange::outputColumn); 
                  <BR>RFX_Text(pFX, _T("[bzm]"), m_bzm); <BR>RFX_Text(pFX, 
                  _T("[dgqd1]"), m_dgqd1); <BR>、、、、、、; <BR>RFX_Text(pFX, 
                  _T("[dgdl2]"), m_dgdl2); <BR>RFX_Text(pFX, _T("[bz]"), m_bz); 
                  <BR>//}}AFX_FIELD_MAP 
                  <BR>pFX-&gt;SetFieldType(CFieldExchange::param); 
                  <BR>//把字段类型设为CFieldExchange::param 
                  <BR>RFX_Text(pFX,"mbzm",mbzm); //为参数设置RFX 
                  宏,如果有多个参数,必须按SQL的语句中的位置标志符的顺序设置,RFX 
                  宏中的参数的名字如"mbzm",并非用来与参数匹配,可以自己定义。 <BR>} <BR>3.2.3 
                  增加第二个表,并设置第二个表的参数 <BR>在3。2。1创建的数据库应用程序基础上,进入ClassWizard,点击Add 
                  Class...按钮并在弹出的菜单中选择New...,然后在Create New 
                  Class对话框中的Name栏中输入CZf1001,在Base class栏中选择CRecordset,按Create按钮。 
                  <BR>在弹出的Database 
                  Options对话框中,在ODBC组合框里选择DB-FSB数据源。然后按OK按钮。在弹出的Select Database 
                  Tables对话框中选择DBK1表。按OK确认。并在所有存在 #include "CZf0001Set.h" 
                  的文件中,都加入#include "CZf1001.h" 。这样就创建了与DBK1表对应的Crecordset派生类。 
                  <BR>在第一步创建的CZf0001Doc类中,增加一个CZf1001 对象的指针变量m_zf1002(即:CZf1001* 
                  m_zf1002)。 <BR>按3.2.2介绍的CZf0001Set类m 
                  _strFilter参数的设置方法,在CZf1001类中,设置参数mhh。 <BR>3. 3 
                  参数mhh及参数mbzm在CrecordView的派生类CZf0001View中的使用 <BR>3.3.1 
                  参数在CZf0001View::OnInitialUpdate()函数使用 
                  <BR>在CZf0001View::OnInitialUpdate()函数的开头部分,调用CZf0001View:: 
                  GetDocument()从文档类CZf0001Doc类中,返回二个CrecordSet类(CZf0001Set、CZf1001)的指针。根据返回的指针,设置m 
                  _strFilter (相当于SQL语句的WHERE子句),并确定二个参数的初始值。这里要说明一点: 
                  <BR>m_pSet-&gt;m_strFilter="BZM like ?"; 
                  <BR>m_pSet2-&gt;m_strFilter="hh like ?"; 
                  <BR>语句中的“?”,在调用Open或Requery时,“?"将分别自动地被CZf0001Set::mbzm和 
                  CZf1001::mhh的值取代。例如,指定mbzm为“31001",则m_pSet-&gt;m_strFilter将变成"BZM 
                  =31001"。这样用户只要指定了mbzm,就可以得到所需要的记录集。CZf0001View::OnInitialUpdate()的程序清单如下(黑体部分的语句是手工增加的): 
                  <BR>void CZf0001View::OnInitialUpdate() <BR>{ m_pSet = 
                  &amp;GetDocument()-&gt;m_zf0001Set; 
                  <BR>m_pSet2=&amp;GetDocument()-&gt;m_zf1002; 
                  <BR>if(!m_pSet2-&gt;Open()) <BR>return; 
                  <BR>m_pSet-&gt;m_strFilter="BZM like ?"; <BR>m_pSet-&gt;mbzm= 
                  "%"; //初始选择所有记录 <BR>m_pSet-&gt;m_strSort=""; 
                  <BR>m_pSet2-&gt;m_strFilter="hh like ?"; 
                  <BR>m_pSet2-&gt;mhh=m_pSet-&gt;m_bzm; 
                  //将表FSB对应的CRecordset派生类的m_bzm的值,作为参数mhh的值  
                  <BR>m_pSet2-&gt;m_strSort="";  //检索的结果不进行排序 
                  <BR>m_pSet-&gt;m_pDatabase= m_pSet2-&gt;m_pDatabase; 
                  //共享CDatabase <BR><BR>CRecordView::OnInitialUpdate(); 
                  <BR>GetParentFrame()-&gt;RecalcLayout(); 
                  <BR>ResizeParentToFit(); <BR>} <BR>3.3.2 在对话框中加入编辑框 
                  <BR>在资源视图Dialog的IDD_ZF0001_FORM表单中,加入用户需要的编辑框。用ClassWizard在第一个表FSB中选择有关字段与它们相连。但是.使用ClassWizard无法找到第二个表DBK1字段变量,因此,对于计划与第二个表DBK1字段相连的编辑框,必须用手工修改CRecordView类的DoDataExchange()(对话框数据交换函数)。 
                  在DoDataExchange()函数 “//}}AFX_DATA_MAP” 
                  后面加入有关内容。见下面程序的黑体部分。如果黑体部分语句加在“//}}AFX_DATA_MAP”的前面,那么,要再次修改IDD_ZF0001_FORM表单时,就无法使用ClassWizard. 
                  <BR>void CZf0001View::DoDataExchange(CDataExchange* pDX) <BR>{ 
                  <BR>CRecordView::DoDataExchange(pDX); 
                  <BR>//{{AFX_DATA_MAP(CZf0001View) <BR>DDX_Control(pDX, 
                  IDC_COMBO1, m_comb); <BR>DDX_Control(pDX, IDC_EDIT4, m_SS); 
                  <BR>DDX_FieldText(pDX, IDC_EDIT2, m_pSet-&gt;m_bl1, m_pSet); 
                  <BR>DDX_FieldText(pDX, IDC_EDIT3, m_pSet-&gt;m_dgdl1, m_pSet); 
                  <BR>DDX_FieldCBString(pDX, IDC_COMBO1, m_pSet-&gt;m_bzm, 
                  m_pSet); <BR>DDX_FieldText(pDX, IDC_EDIT5, m_pSet-&gt;m_dgqd1, 
                  m_pSet); <BR>//}}AFX_DATA_MAP <BR>DDX_FieldText(pDX, 
                  IDC_EDIT1, m_pSet2-&gt;m_bl, m_pSet2); <BR>DDX_FieldText(pDX, 
                  IDC_EDIT6, m_pSet2-&gt;m_hh, m_pSet2); <BR>DDX_FieldText(pDX, 
                  IDC_EDIT7, m_pSet2-&gt;m_zzcm, m_pSet2); <BR>} <BR>3.3.3 
                  在对话框中加入一个按钮 
                  <BR>为演示二个表关联的效果,在对话框中加入一个“关联”按钮和一个输入参数用的"定位"编辑框。并给此按钮增加单击事件代码如下: 
                  <BR><BR>void CZf0001View::OnButton1() <BR>{ <BR>// TODO: Add 
                  your control notification handler code here <BR>char ll[11]; 
                  <BR>int nn=0; <BR>m_SS.GetLine(0,ll); //读“定位”编辑框中的内容 
                  <BR>nn=m_SS.LineLength(0); //读“定位”编辑框中的字符内容的长度 <BR>if(nn) 
                  //“定位”编辑框中有输入内容,则按内容检索形成新的记录集 <BR>{ 
                  m_pSet-&gt;mbzm=(CString)ll; 
                  <BR>m_pSet-&gt;mbzm=m_pSet-&gt;mbzm.Left(nn)+"%"; 
                  //“%”由SQL语法规定代表任意长度(长度可以为0)的字符串 <BR>m_pSet-&gt;Requery(); 
                  //在表FSB中重新检索 <BR>if(m_pSet-&gt;IsEOF()) <BR>{ 
                  MessageBox("检索结果为空!"); <BR>UpdateData(FALSE); 
                  <BR>m_pSet-&gt;mbzm="%"; <BR>m_pSet-&gt;Requery(); <BR>} 
                  <BR>m_pSet2-&gt;Requery(); //以表1当前记录BZM值,在表2:DBK1中检索 
                  <BR>UpdateData(FALSE); //刷新表单内容 <BR>m_SS.SetSel(0,-1); 
                  <BR>m_SS.ReplaceSel(""); 
                  //清除“定位”编辑框中的内容,使下一次单击“关联”按钮时,不会重复检索(即使nn=0) <BR>} <BR>else 
                  //“定位”编辑框为空,则按表1现有的结果集与表2:DBK1关联 <BR>{ 
                  <BR>m_pSet2-&gt;mhh=m_pSet-&gt;m_bzm; 
                  //将表1当前记录BZM值,作为表DBK1的查找参数 <BR>m_pSet2-&gt;Requery(); 
                  <BR>UpdateData(FALSE); <BR>m_pSet-&gt;MoveNext(); <BR>} <BR>} 
                  <BR>4. 小结 <BR>通过本例可知,虽然VC++提供了Appwizard和Classwizard, 
                  为编程者节省了大量的工作,但是想编出优秀的VC++应用程序,仅凭这些是远远不够的;必须熟悉MFC类库、ActiveX控件等知识。本文作为一个例子介绍了二个表的联接方法。在实际的应用中,读者可以举一翻三,编制更加完善的数据库应用程序。 
                  <BR><BR>参考文献 <BR>1. 康博创作室等编著. Visual C++6.0 高级开发教程. 人民邮电出版社 
                  <BR>2. 齐舒创作室 编著. Visual C++6.0编程技巧与实例分析. 中国水利水 电出版社 <BR>3. 官章全 
                  刘加明编著. Visual C++6.0 类库大全. 电子工业出版社 <BR><BR></TD></TR>
              <TR vAlign=center align=right>
                <TD vAlign=bottom bgColor=#ffffff><INPUT style="COLOR: #000000; BACKGROUND-COLOR: #ffffff" onclick=window.close() type=button value=关闭窗口><BR><BR></TD></TR>
              <TR vAlign=center align=right>
                <TD vAlign=center align=middle bgColor=#ffffff>
                  <TABLE id=AutoNumber20 style="BORDER-COLLAPSE: collapse" 
                  borderColor=#111111 cellSpacing=0 cellPadding=0 width="99%" 
                  align=center border=0>
                    <TBODY>
                    <TR>
                      <TD background=用VC++6.0开发多表联接的数据库应用程序.files/bg_dot.gif 
                      colSpan=10 height=1></TD></TR></TBODY></TABLE></TD></TR>
              <TR vAlign=center align=middle>
                <TD bgColor=#ffffff><BR><FONT 
                  color=red><B>特别声明:</B></FONT>文章版权归原作者所有, 未经允许请勿转载, 如有任何问题请<A 
                  href="mailto:webmaster@vczx.com">联系我们</A>. 
              <BR><BR></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE></TD></TR><TR><TD 
align="center" valign="middle">
<CENTER>
<TABLE id=AutoNumber20 style="BORDER-COLLAPSE: collapse" borderColor=#111111 
cellSpacing=0 cellPadding=0 width="100%" align=center border=0>
  <TBODY>
  <TR>
    <TD bgColor=#666666 colSpan=10 height=1></TD></TR></TBODY></TABLE>
<TABLE id=AutoNumber20 style="BORDER-COLLAPSE: collapse" borderColor=#111111 
cellSpacing=0 cellPadding=0 width="100%" border=0>
  <TBODY>
  <TR>
    <TD width="100%"></TD></TR></TBODY></TABLE>
<TABLE borderColor=#799ccc cellSpacing=0 cellPadding=0 width="100%" align=center 
bgColor=#799ccc border=0>
  <TBODY>
  <TR bgColor=#efebef>
    <TD vAlign=center align=middle><BR>| <A class=d 
      href="http://www.vczx.com/"><FONT color=#000000>本站首页</FONT></A> | <A 
      class=d href="http://www.vczx.com/navigation.php" target=_blank><FONT 
      color=#000000>本站地图</FONT></A> | <A class=d 
      href="http://www.vczx.com/aboutus.php" target=_blank><FONT 
      color=#000000>关于本站</FONT></A> | <A class=d 
      href="http://www.vczx.com/copyright.php" target=_blank><FONT 
      color=#000000>版权声明</FONT></A> | <A class=d 
      href="http://www.vczx.com/link.php" target=_blank><FONT 
      color=#000000>友情链接</FONT></A> | <A class=d 
      href="http://www.vczx.com/ad.php" target=_blank><FONT 
      color=#000000>广告投放</FONT></A> | <A class=d 
      href="mailto:webmaster@vczx.com"><FONT color=#000000>联系我们</FONT></A> 
      |</FONT><BR><BR><B><FONT color=#ff0000>特别声明:</FONT><FONT 
      color=#636563></B>如本站所发布内容触犯了您的版权,请<A 
      href="mailto:webmaster@vczx.com"><B>来信</B></A>告诉我们,我们会立即删除。</FONT><BR><FONT 
      face=宋体 color=#636563>Copyright &copy; 2003-2004 <B><FONT face=Verdana 
      color=#000000>vczx</FONT><FONT face=Verdana color=#ce0000>.com</FONT></B> 
      Inc. All rights reserved.</FONT> </TD></TR>
  <TR bgColor=#efebef>
    <TD vAlign=center align=middle><FONT face=宋体 color=#636563>版权所有 &copy; 
      2003-2004 vc在线 本站由loose_went制作维护</FONT><BR>
      <SCRIPT language=JavaScript1.2>				<!--		var correctwidth=1024		var correctheight=768		if (screen.width!=correctwidth||screen.height!=correctheight)		document.write("<font color=#999999>本站最佳分辨率"+correctwidth+"*"+correctheight+",您当前的分辨率是"+screen.width+"*"+screen.height+".<br>设置合适的分辨率才能取得最佳的显示效果!</font>")		//-->		</SCRIPT>
    </TD></TR></TBODY></TABLE></CENTER></TD></TR></TABLE></BODY></HTML>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?