VC中使用ADO调用存储过程实现方法

转载 2011年01月10日 13:50:00

 

本文转自:http://www.cppblog.com/Lee7/archive/2008/06/17/53775.html

 

开发环境是VS2005  ,数据库是SQL Sever 2000

1. 在进入正题之前,先讲点别的,如何在VC中连接Sybase数据库,

   连接字符窜为,

  _bstr_t strCnn(/"Driver={Sybase System 11};Srvr=RRRRR;Uid=RRR_Mao_bb1;Pwd=user2/");

这里,RRRRR是数据库的名称,已经在Sybase->sdedit中设定好了

 RRR_Mao_bb1 和 user2分别是用户名和密码

 不过使用这种基于ODBC的连接使用一段时间以后,就出现问题了,出现了“Catastrophic failure”的错误,微软的解释是  http://support.microsoft.com/kb/243349/en-us

 

2. 为了使我们的调用存储过程的例子有更多的通用性,我建了有输入参数,有输出参数,有一个返回记录集,有一个返回值的存储过程,如下

   
CREATE  PROCEDURE sp_1  (
                         @pin1  int ,
                         @pin2  CHAR(10),
                         @pout1 int OUTPUT,
                         @pout2 CHAR(10)  OUTPUT
                       )
AS                       
BEGIN
  declare  @retval  int
  
  select @pout1 = @pin1 + 100
  
  select @pout2 =  left( ltrim(rtrim(@pin2)) + /'123/' , 10)
  
  select Num,Name,Date 
    from TABLE1
    
  select @retval =  1236
  
  return @retval
END

对于这个SP来说,他这些个参数是

@RETURN_VALUE(int ,返回值)  

@pin1 ( int  ,输入 )  

@pin2 ( char(10)  ,输入 ) 

@pout1 (int ,输入/输出) 

@pout1 ( char(10)  , 输入/输出)  

@RETURN_VALUE是第0个参数,@pin1是第1个,依此类推

以上信息可以在SQL 的查询分析器中看到,注意,这些参数的顺序很重要

 

3.调用的前期准备

  这就不多说了,什么import 库阿,建立连接阿,什么的,不多说了,

 这些在 VC中使用ADO进行数据库开发的一些资料的整理 中有了阐述

假定连接是pConn

注意,这里要把pConn设定成adUseClient型[Page]

pConn->CursorLocation =adUseClient;

下面我要贴具体的代码了,为了精简所贴的代码,我把所有的捕获异常都没贴出来(try catch)

 

4.使用Refresh的方法来调用

先定义一些变量

 _CommandPtr     pCmd = NULL;
 _RecordsetPtr   pRecordset = NULL;

初试化他们,

 pCmd.CreateInstance(__uuidof(Command));
  pRecordset.CreateInstance(_uuidof(Recordset));
  pCmd->ActiveConnection = pConn;
  pCmd->CommandType = adCmdStoredProc;
  pCmd->CommandText=_bstr_t(_T(/"sp_1/"));  //SP Name

然后给那些input参数赋值

 pCmd->Parameters->Refresh();   
  
pCmd->Parameters->Item[_variant_t(_bstr_t(/"@pin1/") )]->Value=_variant_t(3);  

 pCmd->Parameters->Item[_variant_t(_bstr_t(/"@pin2/") )]->Value=_variant_t(/"DD/");  

这个refresh一定要有,

调SP

pRecordset =  pCmd->Execute(NULL,NULL,adCmdStoredProc);

int   retVal = -1;
 _variant_t   VretVal ;

//GetRetVal 
  VretVal = pCmd->Parameters->GetItem(short(0))->Value;
  
  retVal = VretVal.lVal;
   
  Info.Format(_T(/"The Return Value is : %d/"),retVal);
  MessageBox(Info);


  //output1 
  VretVal = pCmd->Parameters->GetItem(short(3))->Value; 
  retVal = VretVal.lVal;
   
  Info.Format(_T(/"The output1 Value is : %d/"),retVal);
  MessageBox(Info);

  //@pout2 
  VretVal = pCmd->Parameters->GetItem(short(4))->Value;
  
  Info= (LPCTSTR)_bstr_t(VretVal);
  CString info1;
  info1.Format(_T(/"The output2 Value is : %s/"),Info);
  
  MessageBox(info1);

 //取记录集里面的内容


  if (pRecordset->adoBOF && pRecordset->adoEOF)
  {
   MessageBox(/"没有符合条件的记录存在!/",/"提示/");

   if(pRecordset != NULL && pRecordset->State)
   {
    pRecordset->Close();
    pRecordset = NULL; 

}

 

   pCmd.Detach();
   return;
  } 
  
  pRecordset->MoveFirst();
  
  for(;!pRecordset->adoEOF;pRecordset->MoveNext())
  {
   VRectVal = pRecordset->GetCollect(_T(/"Name/"));
   StrVal = (LPCTSTR)_bstr_t(VRectVal);
   m_list.AddString(StrVal);
  }

  if(pRecordset != NULL && pRecordset->State)
  {
   pRecordset->Close();
   pRecordset = NULL;  [Page]
  }

最后pCmd.Detach();

 在这里,有一点要注意的是

VretVal = pCmd->Parameters->GetItem(short(4))->Value;
这里的4,就是哪个output参数的index,就是我在2中说的参数的顺序

这里使用了Refresh,这是一个很重要的函数,我将在下面介绍一下它,我要先贴出另一种,不使用Refresh的办法,

5 .使用非Refresh的方法来调用

先定义变量

_CommandPtr     pCmd = NULL;
 _RecordsetPtr   pRecordset = NULL;


 _ParameterPtr   retParam = NULL;   
    _ParameterPtr   inParam1 = NULL;  
 _ParameterPtr   inParam2 = NULL;  
 _ParameterPtr   outParam1 = NULL; 
 _ParameterPtr   outParam2 = NULL; 

初试化


        pCmd.CreateInstance(__uuidof(Command));
  pRecordset.CreateInstance(_uuidof(Recordset));

retParam.CreateInstance(__uuidof(Parameter));

//其他的ParameterPtr   也初试化
  pCmd->ActiveConnection = pConn;
  pCmd->CommandType = adCmdStoredProc;
   pCmd->CommandText=_bstr_t(_T(/"sp_1/"));  //SP Name

 retParam = pCmd ->CreateParameter(_bstr_t(/"Return/"),
                                 adInteger,
            adParamReturnValue,
            sizeof(int));
  pCmd->Parameters->Append(retParam);

  
  
        inParam1  = pCmd ->CreateParameter(_bstr_t(/"InParam1/"),
                                 adInteger,
            adParamInput,
            sizeof(int));

  inParam1->Value = _variant_t(3);

  pCmd->Parameters->Append(inParam1);


  inParam2  = pCmd ->CreateParameter(_bstr_t(/"InParam2/"),
                                 adChar,
            adParamInput,[Page]
            10);
 
  inParam2->Value = _variant_t(_T(/"DD1/"));

  pCmd->Parameters->Append(inParam2);


  outParam1 = pCmd ->CreateParameter(_bstr_t(/"OutParam1/"),
                                 adInteger,
            adParamOutput,
            sizeof(int));
  pCmd->Parameters->Append(outParam1);


  outParam2 = pCmd ->CreateParameter(_bstr_t(/"OutParam2/"),
                                 adChar,
            adParamOutput,
            10);
  pCmd->Parameters->Append(outParam2);

 

这里不用refresh的办法,是用Parameter来,这里要注意的是,这个add的顺序要和参数的index顺序要一致

下面就是调用了

pRecordset =  pCmd->Execute(NULL,NULL,adCmdStoredProc);

然后取那些return值阿,output值阿什么的

这里有一个区别,就是用这种办法

可以有三种办法来取这些返回值和output参数

VretVal = pCmd->Parameters->GetItem(_bstr_t(/"Return/"))->Value;
VretVal = pCmd->Parameters->GetItem(short(0))->Value;
 VretVal = retParam->Value;

都是一样的

6. 关于Refresh

关于这个函数,作用是

Command   对象去重新索取要操作的存储过程所有有关参数的信息,并且清空在refresh之前获取的参数信息。  

所以一但调用它以后,就可以获取SP的那些信息,那些参数的信息,可以通过pCmd->Parameters->Item[_variant_t(_bstr_t(/"@pin1/") )]->Value=_variant_t(3);   这样的方式来设置参数

如果要使用Parameter的办法的话,就不要用refresh了,事实上,如果先把这些参数的值设置好了,如  inParam2->Value = _variant_t(_T(/"DD1/"));,一旦refresh后,这些参数就没有意义了。

7.关于pConn->CursorLocation =adUseClient;

 设置这个东西,如果不设置游标为adUseClient,那么我在取return和output参数的时候,必须在我把记录集关闭以后才能取,就是说,必须先取记录集,然后关闭它,最后再取return和output参数,如果我在关闭记录集之前就取return和output的值,那么就不能取到正确的值,设成adUseClient就ok了,

另外有一点就是,Execute 方法返回的游标继承该设置。Recordset 将自动从与之关联的连接中继承该设置。我把pConn设成adUseClient,那么最后,我的记录集也是adUseClient的了[Page]

 

//注:

本文说明的方法:

 

或直接用下面方法:

 

 

相关文章推荐

VC++ ADO调用存储过程方法

约定: 斜体字体表示可变部分   斜体 红色字体表示固定部分   红体   以下步骤的前提条件:COM ADO库已初始化,已经设置_ConnectionPtr连接对象。   步骤一: 创...

vc中ADO执行存储过程方法记录

ado执行存储过程,需要用到_CommandPtr接口。 方法如下: 可将如下代码段放在数据类初始化连接中_CommandPtr m_pCommand; // 定义_Com...
  • starytx
  • starytx
  • 2017年04月20日 17:20
  • 289

VC ado调用oracle执行存储过程获取记录集

最近在做一个项目,数据库是用SQL Server,不过最近突然来了个需求说要改用Oracle。之前对SQL Server ado访问层做了一些封装,想试试看能不能简单修改后兼容oracle。测试过程中...
  • imlmy
  • imlmy
  • 2013年05月07日 14:33
  • 2381

vc++中,ado执行sql server存储过程

_variant_t RecordsAffected; string szSql = (string)"P_KS_ADDUSER " + m_szName+ "," + m_szPasswd +";"...

C#二十六 使用Ado.Net调用存储过程

存储过程是连接式访问数据库的一种延伸,主要是通过命令对象调用数据库系统中的存储过程来完成的。存储过程可以带参数,也可以不带参数,可以返回结果页可以没有返回结果。存储过程执行速度快、允许模块化程序设计并...

Excel使用ADO调用SQL Server存储过程

前期使用Excel做一个现场投票的小软件,问题出在查看投票按钮上,起初只是使用SELECT语句查询,一切正常;后期对于投票结果需要进行一些权重的计算,过程比较复杂,便想到把计算过程放在SQL Serv...

VC调用存储过程的通用方法(SQLServer篇)

这里讨论的是ADO调用存储过程,按MSDN的例子,一般都是下面的调用方法(节选自MSDN): HRESULT hr = S_OK;     // Define ADO object point...

用ADO.NET调用存储过程.ppt

  • 2009年08月03日 19:53
  • 126KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:VC中使用ADO调用存储过程实现方法
举报原因:
原因补充:

(最多只允许输入30个字)