如何在vc 中用ado  调用sql server  的存储过程?
希望给出详细代码和在vc++6.0(利用MFC)的详细步骤。
非常感谢!(最好能解释一下参数的意思)

解决方案 »

  1.   

    用ADO操作数据库的方法步骤
            
    /***********************ADO接口简介 ***********************************/
    ADO库包含三个基本接口:_ConnectionPtr接口、_CommandPtr接口和_RecordsetPtr接口。 _ConnectionPtr接口返回一个记录集或一个空指针。
    通常使用它来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
    使用_ConnectionPtr接口返回一个记录集不是一个好的使用方法。
    通常同Cdatabase一样,使用它创建一个数据连接,然后使用其它对象执行数据输入输出操作。_CommandPtr接口返回一个记录集。
    它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。
    在使用_CommandPtr接口时,你可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。
    如果你只执行一次或几次数据访问操作,后者是比较好的选择。
    但如果你要频繁访问数据库,并要返回很多记录集,那么,你应该使用全局_ConnectionPtr接口创建一个数据连接,
    然后使用_CommandPtr接口执行存储过程和SQL语句。
     _RecordsetPtr是一个记录集对象。
    与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定,游标控制等
    。同_CommandPtr接口一样,它不一定要使用一个已经创建的数据连接,
    可以用一个连接串代替连接指针赋给_RecordsetPtr的connection成员变量,让它自己创建数据连接。
    如果你要使用多个记录集,最好的方法是同Command对象一样使用已经创建了数据连接的全局_ConnectionPtr接口
    ,然后使用_RecordsetPtr执行存储过程和SQL语句。
    /***********************基本流程***********************************/
    (1)初始化COM库,引入ADO库定义文件
    (2)用Connection对象连接数据库
    (3)利用建立好的连接,通过Connection、Command对象执行SQL命令,或利用Recordset对象取得结果记
       录集进行查询、处理。
    (4)使用完毕后关闭连接释放对象。 /***********************【1】COM库的初始化***********************************/
    我们可以使用AfxOleInit()来初始化COM库,这项工作通常在CWinApp::InitInstance()的重载函数中完
    成,请看如下代码:
    //也可以使用::CoInitialize(NULL);
    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) 
    { ...} ◆(2)利用 Command对象 来执行SQL命令
     try
     {
      _CommandPtr m_pCommand; 
      m_pCommand.CreateInstance("ADODB.Command");
      
      m_pCommand->ActiveConnection = m_pConnection; //关键的一句,将建立的连接赋值给它  m_pCommand->CommandText="INSERT INTO 学生信息(学号,姓名,年龄,生日) VALUES (112105, '程红秀',22,'1982-08-16')";
      m_pCommand->Execute(NULL,NULL,adCmdText);
     
      m_pCommand->CommandText="SELECT COUNT(*) FROM 学生信息";
      m_pRecordset=m_pCommand->Execute(NULL,NULL,adCmdText);  _variant_t vCount = m_pRecordset->GetCollect((_variant_t)(long)0); //取得第一个字段的值
      
      CString str;
      str.Format("共有%d条记录",vCount.lVal);
      AfxMessageBox(str);     m_pRecordset->Close();  }
     catch (_com_error e) {...}在这段代码中我们只是用Command对象来执行了SELECT查询语句,
    Command对象在进行存储过程的调用中能真正体现它的作用。下次我们将详细介绍。 
      

  2.   

    用那三个接口都可以执行SQL语句,这里说的SQL语句就是可以在查询分析器里面执行的,当然包括存储过程
      

  3.   

    这里有别人的代码,我试过,正确运行,你参考一下。_ConnectionPtr m_pConnection;
     _CommandPtr m_pCommand;
    .cpp中在函数中执行
    //建立ado连接
     HRESULT hr;
     hr=m_pConnection.CreateInstance(__uuidof(Connection));
     try
     {
     if(SUCCEEDED(hr))
     {
     hr=m_pConnection->Open(_bstr_t(L"Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=Viper;Data Source=Viper"),_bstr_t (L"sa"),_bstr_t (L""),adModeUnknown);
     }
     }
     catch(_com_error & err)
     {
     AfxMessageBox(err.Description(),MB_OK,0);
     AfxMessageBox(err.ErrorMessage(),MB_OK,0);
     AfxMessageBox("无法连接SQL SERVER 服务器,程序将退出。请检查网络设备",MB_OK,0);
     exit(0);
     }//执行储存过程
     CString cvar1,cvar2;
     int cvar3;
     cvar1="ddd";
     cvar2="";
     cvar3=0;
     try
     {
     m_pCommand.CreateInstance(__uuidof(Command));
     m_pCommand->ActiveConnection=app->m_pConnection;
     m_pCommand->CommandType=adCmdStoredProc;
     m_pCommand->CommandText=_bstr_t("pr_zs_dzdy"); _variant_t vvar1,vvar2,vvar3;
     vvar1=_variant_t(_bstr_t(cvar1));
     vvar2=_variant_t(_bstr_t(cvar2));
     vvar3=_variant_t(cvar3);
     _ParameterPtr mp_var1,mp_var2,mp_var3;
     mp_var1.CreateInstance(__uuidof(Parameter));
     mp_var2.CreateInstance(__uuidof(Parameter));
     mp_var3.CreateInstance(__uuidof(Parameter)); mp_var1=m_pCommand->CreateParameter
     (
     _bstr_t("var1"),
     adVarChar,
     adParamInput,
     3,
    vvar1
    );
     m_pCommand->Parameters->Append(mp_var1);  mp_var2=m_pCommand->CreateParameter
     (
     _bstr_t("var2"),
     adVarChar,
     adParamOutput,
     3,
     vvar2
     );
     m_pCommand->Parameters->Append(mp_var2);  mp_var3=m_pCommand->CreateParameter
     (
     _bstr_t("var3"),
     adIntger,
     adParamOutput,
     9,
     vvar3
     );
     m_pCommand->Parameters->Append(mp_var3); 
     _variant_t vNull;
     vNull.vt=VT_ERROR;
     vNull.scode=DISP_E_PARAMNOTFOUND;
     m_pCommand->Execute(&vNull,&vNull,adCmdStoredProc);
     cvar2=mp_var2->Value.bstrVal;
     cvar3=mp_var3->Value;
     }
     catch(_com_error &error)
     {
     MessageBox(error.ErrorMessage(),"ADO错误!");
     MessageBox(error.Description(),"ADO错误!");
     }
      

  4.   


    用 Command 对象执行存储过程,例子中的存储过程还带有输入参数。