VC中使用ADO调用存储过程

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型

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;
}

最后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,
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的了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值