MFC 访问Access数据库 建立并执行存贮过程

MFC 访问Access数据库  建立并执行存贮过程

在学习VC ADO访问数据库时,每次遇到带参数的查询或者存贮过程时,就比较反感,因为印象中好像就是SQl 才支持这些操作,因此在网上到处搜集关于Access中执行存贮过程和带参数查询的问题。可是网上很多帖子和作者,感觉讲的不够清楚,或者干脆不负责任的说Access不支持存贮过程,或者把这个过程说的过于复杂,好像很难一样。我通过之前学习《直接通过ADO操作Access数据库》(作者徐景周)以及查看了一些帖子之后,自己动手利用Access 2003 成功的建立了存贮过程 ,并且利用VC 可以进行方便的操作。在此我把所学习的内容分享给一些和我一样想快速入门的学生。

在Access 2003 中建立表的数据结构及初始化的数据:

 

 

 

在Access中建立存贮过程的代码和执行存贮过程的过程:

 

在VC中的代码:

注意我使用的是控件关联变量,说明如下

CListBox m_AccessList;//列表框控件 控件型
 CString m_strClass;//学生的班级  字符串型
 CString m_strName;//学生的姓名 字符串型

 CString m_strSno;//学生的学号 字符串型

 int  m_nAge;//学生的年龄   整型

public:
 _RecordsetPtr m_pRecordset;
 _ConnectionPtr m_pConnection;

CEditRecord 是一个编辑记录输入对话框(class CEditRecord : public CDialog)如下:

其中的一些函数建立消息映射在此不列出,相信你做VC连接数据库操作,应该有这个基础.

一下是class CAdoDlg 的实现文件

// AdoDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Ado.h"
#include "AdoDlg.h"
#include "EditRecord.h"
// CAdoDlg dialog
CAdoDlg::CAdoDlg(CWnd* pParent /*=NULL*/)
 : CDialog(CAdoDlg::IDD, pParent)
{
 //{{AFX_DATA_INIT(CAdoDlg)
 m_strClass = _T("");
 m_strName = _T("");
 m_strSno = _T("");
 m_nAge = 0;
 //}}AFX_DATA_INIT
 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 // 初始化COM,创建ADO连接等操作
 AfxOleInit();
 m_pConnection.CreateInstance(__uuidof(Connection));
 m_pRecordset.CreateInstance(__uuidof(Recordset));
}
/
// CAdoDlg message handlers
BOOL CAdoDlg::OnInitDialog()
{   
  //之前代码未作任何更改 由VC系统自动生成 此处不列出
  // TODO: Add extra initialization here
 InitData();//初始列表框数据
  return TRUE;  // return TRUE  unless you set the focus to a control
}
//插入新记录
void CAdoDlg::OnBtnInsert() 
{
 // TODO: Add your control notification handler code here
 try
 { 
  // 写入各字段值
  m_pRecordset->AddNew();
  UpdateData();//千万记住要更新操作,从控件获取数据
  CString strage;
  strage.Format("%d",m_nAge);
  m_pRecordset->PutCollect("学号", _variant_t (m_strSno));
  m_pRecordset->PutCollect("姓名", _variant_t (m_strName));
  m_pRecordset->PutCollect("年龄", _variant_t (strage));
  m_pRecordset->PutCollect("班级", _variant_t (m_strClass));
  m_pRecordset->Update();
     LoadData(m_pRecordset);
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 }      
}
//执行更新记录的存贮过程
void CAdoDlg::OnBtnMod()
{
 // TODO: Add your control notification handler code here
 // TODO: Add your control notification handler code here
 _CommandPtr m_pCommand;//智能指针
    m_pCommand.CreateInstance(__uuidof( Command ));//实例
    //用_ParameterPtr智能指针来建立参数
 _ParameterPtr m_pParam;
 m_pParam.CreateInstance(__uuidof(Parameter));
 //建立好参数
 try
 {   UpdateData();
  m_pParam= m_pCommand->CreateParameter("Sno",adVarChar,adParamInput,15,(_variant_t)m_strSno);// 给参数设置各属性
  m_pCommand->Parameters->Append(m_pParam);//学号 加入到Command对象的参数集属性中
  m_pParam= m_pCommand->CreateParameter("Sname",adVarChar,adParamInput,20,(_variant_t)m_strName);
  m_pCommand->Parameters->Append(m_pParam);//姓名 加入到Command对象的参数集属性中
  m_pParam = m_pCommand->CreateParameter("Sage",adInteger,adParamInput,-1,(_variant_t)((long)m_nAge));
  m_pCommand->Parameters->Append(m_pParam);//年龄 加入到Command对象的参数集属性中
  m_pParam= m_pCommand->CreateParameter("Sclass",adVarChar,adParamInput,5,(_variant_t)m_strClass);
  m_pCommand->Parameters->Append(m_pParam);//班级 加入到Command对象的参数集属性中
  m_pCommand->CommandText="Proc_UpdateName";
  m_pCommand->ActiveConnection=m_pConnection;
  m_pCommand->Execute(NULL, NULL,adCmdStoredProc); // 执行更新数据存贮过程,注意此时不返回记录集
  m_AccessList.ResetContent();
        if(!m_pRecordset->adoEOF)
            m_pRecordset->MoveFirst();
  while(!m_pRecordset->adoEOF)
  {
   LoadData(m_pRecordset);
   m_pRecordset->MoveNext();
  }
 }
 catch(_com_error &e)
 {  
   CString Error;
   long i,cnt;
   cnt=m_pConnection->Errors->Count;
   Error+=e.ErrorMessage();
   for(i=0;i<cnt;i++)
   {
   Error+=(LPCSTR)(m_pConnection->Errors->GetItem(_variant_t(i))->Description );
   }
   AfxMessageBox(Error);
 }
} 
//初始列表框数据
int CAdoDlg::InitData()
{
 if(m_pConnection->IsolationLevel)
  try                 
  { 
   // 打开本地Access库
   m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=STUMGR.mdb","","",adModeUnknown);
  }
  catch(_com_error e)
  {
   AfxMessageBox("数据库连接失败,确认数据库是否在当前路径下!",MB_OK|MB_ICONHAND);
   return FALSE;
  } 
 // 在ADO操作中建议语句中要常用try...catch()来捕获错误信息,
 // 因为它有时会经常出现一些意想不到的错误。
 try
 {
  m_pRecordset->Open("SELECT * FROM stu",                // 查询stu表中所有字段
       m_pConnection.GetInterfacePtr(),  // 获取库接库的IDispatch指针
       adOpenDynamic,
       adLockOptimistic,
       adCmdText);
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 } 
 _variant_t var;
    CString strSno,strName,strClass;
 try
 {
  if(!m_pRecordset->BOF)
   m_pRecordset->MoveFirst();
  else
  {
   AfxMessageBox("表内数据为空",MB_OK|MB_ICONHAND);
   return FALSE;
  }
  // 读入库中各字段并加入列表框中
  while(!m_pRecordset->adoEOF)
  {   
   LoadData(m_pRecordset);
   m_pRecordset->MoveNext();
  }
  // 默认列表指向第一项,同时移动记录指针并显示
  m_AccessList.SetCurSel(0);
 }
 catch(_com_error *e)
 {
  AfxMessageBox(e->ErrorMessage());
 } 
 return TRUE;
}
//关闭对话框时释放数据库资源
void CAdoDlg::OnBtnClose()
{
 // TODO: Add your control notification handler code here
 CAdoDlg::OnClose();
}
void CAdoDlg::OnClose()
{
 // TODO: Add your message handler code here and/or call default
 
 if(IDOK==MessageBox("关闭数据库并推出吗?","学生管理",MB_OKCANCEL|MB_ICONEXCLAMATION))
 {
  try{
   if(m_pConnection->State)
    m_pConnection->Close();
   m_pConnection= NULL;  
   if(m_pRecordset->State)
   m_pRecordset->Close();
   m_pRecordset = NULL; 
  }
  catch(_com_error *e)
  {
   AfxMessageBox(e->ErrorMessage());
  } 
   CDialog::OnCancel();
 }
}
//按年龄带参数的查询
void CAdoDlg::OnBtnQuery()
{
 // TODO: Add your control notification handler code here
 
 CString strSno,strName,strClass,strage;
 int nAge;
 //_RecordsetPtr pRecodrset(__uuidof(Recordset));
 _CommandPtr m_pCommand;//还是智能指针
    m_pCommand.CreateInstance(__uuidof( Command ));//实例
    //VC中用_ParameterPtr智能指针来建立参数,具体如下:
 _ParameterPtr m_pParam;
 //m_pParam.CreateInstance("ADODB.Parameter");
 //别高兴还没有真正的建立好参数
 CEditRecord Dlg;
 Dlg.m_strTip="输入年龄:";
 if(IDOK==Dlg.DoModal()) 
 {   
  nAge=atoi(Dlg.m_strInput);
  // 方法一  一次性指定
  //m_pParam = m_pCommand->CreateParameter("Age",adInteger,adParamInput,-1,(_variant_t)(long)nAge);//给参数设置各属性
  //方法二
  /*  
  _variant_t var;
  var.vt=VT_INT;//先指定类型为整型
  var.intVal =nAge;//赋值
  m_pParam = m_pCommand->CreateParameter("Age",adInteger,adParamInput,-1,var);//给参数设置各属性
  */
  //方法三
  m_pParam = m_pCommand->CreateParameter("Age",adInteger,adParamInput,-1);//给参数设置各属性
  m_pParam->Value = (_variant_t)((long)nAge);//后续指定
  m_pCommand->Parameters->Append(m_pParam);//加入到Command对象的参数集属性中
  m_pCommand->CommandText=(_bstr_t)("SELECT * FROM stu WHERE 年龄=?");
  m_pCommand->ActiveConnection=m_pConnection;
  try
  {
   m_pRecordset = m_pCommand->Execute(NULL, NULL,adCmdText); // 执行SQL语句,返回记录集 
   m_AccessList.ResetContent();
   while(!m_pRecordset->adoEOF)
   {
    LoadData(m_pRecordset);
    m_pRecordset->MoveNext();
   }
  }
  catch(_com_error &e)
  {  
   CString Error;
   long i,cnt;
   cnt=m_pConnection->Errors->Count;
   Error+=e.ErrorMessage();
   for(i=0;i<cnt;i++)
    {
    Error+=(LPCSTR)(m_pConnection->Errors->GetItem(_variant_t(i))->Description );
    }
    AfxMessageBox(Error);
  }
 }
}
//从记录集加载数据到列表框和编辑控件
void CAdoDlg::LoadData(_RecordsetPtr pRecordset)
{   
 int nAge;
 CString strSno,strName,strClass,strAge;
    if(!pRecordset->adoEOF)
 {      
      _variant_t var;
   var = m_pRecordset->GetCollect("学号");
   if(var.vt != VT_NULL)
    strSno = (LPCSTR)_bstr_t(var);
   var = m_pRecordset->GetCollect("姓名");
   if(var.vt != VT_NULL)
    strName = (LPCSTR)_bstr_t(var);
   var = m_pRecordset->GetCollect("年龄");
   if(var.vt != VT_NULL)
    nAge = atoi(_bstr_t(var));
   strAge.Format("%d",nAge);
   var = m_pRecordset->GetCollect("班级");
   if(var.vt != VT_NULL)
    strClass = (LPCSTR)_bstr_t(var);
   m_AccessList.AddString( strSno+ " -->"+strName + "-->"+strAge+"-->"+strClass);
   GetDlgItem(IDC_EDIT_SNO)->SetWindowText(strSno);
   GetDlgItem(IDC_EDIT_NAME)->SetWindowText(strName);
   GetDlgItem(IDC_EDIT_AGE)->SetWindowText(strAge);
   GetDlgItem(IDC_EDIT_CLASS)->SetWindowText(strClass); 
 }
}
//按年龄的存贮过程查询
void CAdoDlg::OnBtnProcedure()
{
 // TODO: Add your control notification handler code here
 CString strSno,strName,strClass,strage;
 int nAge;
 //_RecordsetPtr pRecodrset(__uuidof(Recordset));
 _CommandPtr m_pCommand;//智能指针
    m_pCommand.CreateInstance(__uuidof( Command ));//实例
    //用_ParameterPtr智能指针来建立参数
 _ParameterPtr m_pParam;
 //建立好参数
 CEditRecord Dlg;
 Dlg.m_strTip="输入年龄:";
 try
 {
  if(IDOK==Dlg.DoModal())
  {   
   nAge=atoi(Dlg.m_strInput);
   m_pParam = m_pCommand->CreateParameter("Age",adInteger,adParamInput,-1);//给参数设置各属性
   m_pParam->Value = (_variant_t)((long)nAge);
   m_pCommand->Parameters->Append(m_pParam);//加入到Command对象的参数集属性中
   m_pCommand->CommandText="Proc_QueryAge";
   m_pCommand->ActiveConnection=m_pConnection;
   m_pRecordset = m_pCommand->Execute(NULL, NULL,adCmdStoredProc); // 执行SQL语句,返回记录集
   m_AccessList.ResetContent();
   while(!m_pRecordset->adoEOF)
   {
    LoadData(m_pRecordset);
    m_pRecordset->MoveNext();
   }
  }
 }
 catch(_com_error &e)
 {  
   CString Error;
   long i,cnt;
   cnt=m_pConnection->Errors->Count;
   Error+=e.ErrorMessage();
   for(i=0;i<cnt;i++)
   {
   Error+=(LPCSTR)(m_pConnection->Errors->GetItem(_variant_t(i))->Description );
   }
   AfxMessageBox(Error);
 }
}


 

实验中执行按年龄sql带参数查询和执行按年龄存贮过程的查询结果一样。示例如下:

 

当然本文只是提供了执行带参数的查询和存贮过程的简单例子,具体的应用还需要下功夫继续深究,代码已经测试通过,如遇问题,请修改你程序数据库路径、数据库数据类型、对话框结构。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值