数据库

/***********************基本流程***********************************/
(1)初始化COM库,引入ADO库定义文件
(2)用Connection对象连接数据库
(3)利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记
      录集进行查询、处理。
(4)使用完毕后关闭连接释放对象。

 

/***********************【1】COM库的初始化***********************************/
我们可以使用AfxOleInit()来初始化COM库,这项工作通常在CWinApp::InitInstance()的重载函数中完
成,请看如下代码:

BOOL   CADOTest1App::InitInstance()
{
    AfxOleInit();
    ......  
}


/*****************【2】用#import指令引入ADO类型库**********************/
我们在stdafx.h中加入如下语句:
#import   "c:/program   files/common   files/system/ado/msado15.dll "   no_namespace   rename( "EOF ", "adoEOF ")
其最终作用同我们熟悉的#include类似,编译的时候系统会为我们生成msado15.tlh,ado15.tli两个C++头文件来定义ADO库。

 

/***************【3】创建Connection对象并连接数据库********************/

首先我们需要添加一个指向Connection对象的指针:

_ConnectionPtr   m_pConnection;

BOOL   CADOTest1Dlg::OnInitDialog()
{
  CDialog::OnInitDialog();
  try
  {
    HRESULT   hr   =   m_pConnection.CreateInstance( "ADODB.Connection ");//创建Connection对象
    if(SUCCEEDED(hr))
    {
      hr   =   m_pConnection-> Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source=test.mdb ", " ", " ",adModeUnknown);//连接数据库
      //上面一句中连接字串中的Provider是针对ACCESS2000环境的,对于ACCESS97,需要改为:Provider=Microsoft.Jet.OLEDB.3.51;     }
    }
  }
  catch   (_com_error   e)   //COM错误取得,当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
  {    
    CString   strComError;
    strComError.Format( "错误编号:   %08lx/n错误信息:   %s/n错误源:   %s/n错误描述:   %s ",
              e.Error(),                                     //   错误编号
              e.ErrorMessage(),                       //   错误信息
              (LPCSTR)   e.Source(),                 //   错误源
              (LPCSTR)   e.Description());     //   错误描述            
   
    ::MessageBox(NULL,strComError, "错误 ",MB_ICONEXCLAMATION);
  }
}
也可以使用UDL文件进行连接。
try
{    
  m_pConnection.CreateInstance(__uuidof(Connection));      
  m_pConnection-> ConnectionString   = "File   Name=e.udl ";  
  m_pConnection-> Open( " ", " ", " ",NULL);  
}
catch(_com_error   e)
{....}

◆在这段代码中我们是通过Connection对象的Open方法来进行连接数据库的,下面是该方法的原型

HRESULT   Connection15::Open   (_bstr_t   ConnectionString,   _bstr_t   UserID,   _bstr_t   Password,   long   Options   )

ConnectionString   为连接字串,
UserID         是用户名,  
Password       是登陆密码,
Options         是连接选项,用于指定Connection对象对数据的更新许可权,  
          Options可以是如下几个常量:
 
    adModeUnknown:       缺省。当前的许可权未设置
    adModeRead:         只读
    adModeWrite:       只写
    adModeReadWrite:     可以读写
    adModeShareDenyRead:   阻止其它Connection对象以读权限打开连接
    adModeShareDenyWrite:   阻止其它Connection对象以写权限打开连接
    adModeShareExclusive:   阻止其它Connection对象打开连接
    adModeShareDenyNone:   允许其它程序或对象以任何权限建立连接


◆常用的数据库连接方法:

(1)通过JET数据库引擎对ACCESS2000数据库的连接
m_pConnection-> Open( "Provider=Microsoft.Jet.OLEDB.4.0;Data   Source=C://test.mdb ", " ", " ",adModeUnknown);

(2)通过DSN数据源对任何支持ODBC的数据库进行连接:
m_pConnection-> Open( "Data   Source=adotest;UID=sa;PWD=; ", " ", " ",adModeUnknown);
//m_pConnection-> Open( "DSN=test; ", " ", " ",0);       //连接叫作test的ODBC数据源  

(3)不通过DSN对SQL   SERVER数据库进行连接:  
m_pConnection-> Open( "driver={SQL   Server};Server=127.0.0.1;DATABASE=vckbase;UID=sa;PWD=139 ", " ", " ",adModeUnknown);
其中Server是SQL服务器的名称,DATABASE是库的名称

◆先介绍Connection对象中两个有用的属性ConnectionTimeOut与State
ConnectionTimeOut用来设置连接的超时时间,需要在Open之前调用,例如:
    m_pConnection-> ConnectionTimeout   =   5;   //设置超时时间为5秒
    m_pConnection-> Open( "Data   Source=adotest; ", " ", " ",adModeUnknown);

State属性指明当前Connection对象的状态,0表示关闭,1表示已经打开,我们可以通过
读取这个属性来作相应的处理,例如:
if(m_pConnection-> State)
    m_pConnection-> Close();   //如果已经打开了连接则关闭它

 


4】/*****************执行SQL命令并取得结果记录集****************/

为了取得结果记录集,我们定义一个指向Recordset对象的指针:
                _RecordsetPtr   m_pRecordset;
并为其创建Recordset对象的实例:    
                m_pRecordset.CreateInstance( "ADODB.Recordset ");

SQL命令的执行可以采用多种形式,下面我们一进行阐述。

◆(1)利用Connection对象的Execute方法执行SQL命令
Execute方法的原型如下所示:

_RecordsetPtr   Connection15::Execute   (_bstr_t   CommandText,   VARIANT   *   RecordsAffected,   long   Options   )  
其中
    CommandText       是命令字串,通常是SQL命令。
    RecordsAffected     是操作完成后所影响的行数,  
    Options         表示CommandText中内容的类型,Options可以取如下值之一:
              adCmdText:     表明CommandText是文本命令
              adCmdTable:     表明CommandText是一个表名
              adCmdProc:     表明CommandText是一个存储过程
              adCmdUnknown:   未知

Execute执行完后返回一个指向记录集的指针,下面我们给出具体代码并作说明。    
try
{
  _variant_t   ra;
 
  m_pConnection-> Execute( "CREATE   TABLE   学生信息(学号   INTEGER,姓名   TEXT,年龄   INTEGER,生日   DATETIME) ",&ra,adCmdText);
  m_pConnection-> Execute( "INSERT   INTO   学生信息(学号,姓名,年龄,生日)   VALUES   (112105,   '程红秀 ',22, '1982-08-16 ') ",&ra,adCmdText);//往表格里面添加记录
  m_pRecordset   =   m_pConnection-> Execute( "SELECT   COUNT(*)   FROM   学生信息 ",&ra,adCmdText);       //执行SQL统计命令得到包含记录条数的记录集
 
  _variant_t   vCount   =   m_pRecordset-> GetCollect((_variant_t)(long)(0));   //取得第一个字段的值放入vCount变量
 
  m_pRecordset-> Close();  
  CString   message;
  message.Format( "共有%d条记录 ",vCount.lVal);
  AfxMessageBox(message);      
}

catch   (_com_error   e)  
{   ...}

◆(3)直接用Recordset对象进行查询取得记录集  
例如  
    m_pRecordset-> Open( "SELECT   *   FROM   学生信息 ",_variant_t((IDispatch   *)m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);

Open方法的原型是这样的:
HRESULT   Recordset15::Open   (   const   _variant_t   &   Source,   const   _variant_t   &   ActiveConnection,   enum   CursorTypeEnum   CursorType,   enum   LockTypeEnum   LockType,   long   Options   )  
其中:
  ①Source是数据查询字符串
  ②ActiveConnection是已经建立好的连接(我们需要用Connection对象指针来构造一个_variant_t对象)  
  ③CursorType光标类型,它可以是以下值之一,请看这个枚举结构:
      enum   CursorTypeEnum
      {
        adOpenUnspecified   =   -1,   //不作特别指定
        adOpenForwardOnly   =   0,   //前滚静态光标。这种光标只能向前浏览记录集,比如用MoveNext向前滚动,这种方式可以提高浏览速度。但诸如BookMark,RecordCount,AbsolutePosition,AbsolutePage都不能使用
        adOpenKeyset   =   1,     //采用这种光标的记录集看不到其它用户的新增、删除操作,但对于更新原有记录的操作对你是可见的。
        adOpenDynamic   =   2,     //动态光标。所有数据库的操作都会立即在各用户记录集上反应出来。
        adOpenStatic   =   3     //静态光标。它为你的记录集产生一个静态备份,但其它用户的新增、删除、更新操作对你的记录集来说是不可见的。
      };
  ④LockType锁定类型,它可以是以下值之一,请看如下枚举结构:
      enum   LockTypeEnum
      {
        adLockUnspecified   =   -1,     //未指定
        adLockReadOnly   =   1,       //只读记录集
        adLockPessimistic   =   2,     //悲观锁定方式。数据在更新时锁定其它所有动作,这是最安全的锁定机制
        adLockOptimistic   =   3,     //乐观锁定方式。只有在你调用Update方法时才锁定记录。在此之前仍然可以做数据的更新、插入、删除等动作
        adLockBatchOptimistic   =   4,   //乐观分批更新。编辑时记录不会锁定,更改、插入及删除是在批处理模式下完成。
      };  
  ⑤Options请参考本文中对Connection对象的Execute方法的介绍

 


/***********************【5】记录集的遍历、更新*************************/

根据我们刚才通过执行SQL命令建立好的   学生信息   表,它包含四个字段:学号,姓名,年龄,生日
以下的代码实现:打开记录集,遍历所有记录,删除第一条记录,添加三条记录,移动光标到第二条
记录,更改其年龄,保存到数据库。

  try
  {
    _variant_t   vUsername,vBirthday,vID,vOld;
    _RecordsetPtr   m_pRecordset;
   
    m_pRecordset.CreateInstance( "ADODB.Recordset ");
    m_pRecordset-> Open( "SELECT   *   FROM   学生信息 ",_variant_t((IDispatch*)m_pConnection,true),adOpenStatic,adLockOptimistic,adCmdText);
   
    while(!m_pRecordset-> adoEOF)  
    {
      vID   =   m_pRecordset-> GetCollect(_variant_t((long)0));         //取得第1列的值,从0开始计数,你也可以直接给出列的名称,如下一行
      vUsername   =   m_pRecordset-> GetCollect( "姓名 ");     //取得姓名字段的值
      vOld   =   m_pRecordset-> GetCollect( "年龄 ");
      vBirthday   =   m_pRecordset-> GetCollect( "生日 ");
     
      TRACE( "id:%d,姓名:%s,年龄:%d,生日:%s/r/n ",
        vID.lVal,
        (LPCTSTR)(_bstr_t)vUsername,
        vOld.lVal,
        (LPCTSTR)(_bstr_t)vBirthday);     //在DEBUG方式下的OUTPUT窗口输出记录集中的记录
 
      m_pRecordset-> MoveNext();         //移到下一条记录
    }
   
    m_pRecordset-> MoveFirst();         //移到首条记录
    m_pRecordset-> Delete(adAffectCurrent);         //删除当前记录
   
   
    for(int   i=0;i <3;i++)         //添加三条新记录并赋值
    {
      m_pRecordset-> AddNew();         //添加新记录
      m_pRecordset-> PutCollect( "学号 ",_variant_t((long)(i+10)));
      m_pRecordset-> PutCollect( "姓名 ",_variant_t( "王斌年 "));
      m_pRecordset-> PutCollect( "年龄 ",_variant_t((long)21));
      m_pRecordset-> PutCollect( "生日 ",_variant_t( "1930-3-15 "));
    }
   
    m_pRecordset-> Move(1,_variant_t((long)adBookmarkFirst));         //从第一条记录往下移动一条记录,即移动到第二条记录处
    m_pRecordset-> PutCollect(_variant_t( "年龄 "),_variant_t((long)45));         //修改其年龄
    m_pRecordset-> Update();         //保存到库中
   
  }   catch   (_com_error   e){}

 

/***********************【6】关闭记录集与连接   *************************/
记录集或连接都可以用Close方法来关闭              
  m_pRecordset-> Close();   //关闭记录集    
  m_pConnection-> Close();   //关闭连接  

 


在stdafx.h中进行宏定义:
#if   !defined   CATCH_ERROR
#define   CATCH_ERROR                       /
    {                           /
      CString   strComError;               /
      strComError.Format( "错误编号:   %08lx/n错误信息:   %s/n错误源:   %s/n错误描述:   %s ",   /
                e.Error(),                                     /
                e.ErrorMessage(),                       /
                (LPCSTR)   e.Source(),                 /
                (LPCSTR)   e.Description());     /
      ::MessageBox(NULL,strComError, "错误 ",MB_ICONEXCLAMATION);   /
    }
#endif
使用方法:
try
{     ...}
catch(_com_error   e)
{
  CATCH_ERROR;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值