VC中使用ADO調(diào)用存儲(chǔ)過(guò)程實(shí)現(xiàn)方法
開(kāi)發(fā)環(huán)境是VS2005 ,數(shù)據(jù)庫(kù)是SQL Sever 2000
1. 在進(jìn)入正題之前,先講點(diǎn)別的,如何在VC中連接Sybase數(shù)據(jù)庫(kù),
連接字符竄為,
_bstr_t strCnn(\"Driver={Sybase System 11};Srvr=RRRRR;Uid=RRR_Mao_bb1;Pwd=user2\");
這里,RRRRR是數(shù)據(jù)庫(kù)的名稱,已經(jīng)在Sybase->sdedit中設(shè)定好了
RRR_Mao_bb1 和 user2分別是用戶名和密碼
不過(guò)使用這種基于ODBC的連接使用一段時(shí)間以后,就出現(xiàn)問(wèn)題了,出現(xiàn)了“Catastrophic failure”的錯(cuò)誤,微軟的解釋是 http://support.microsoft.com/kb/243349/en-us
2. 為了使我們的調(diào)用存儲(chǔ)過(guò)程的例子有更多的通用性,我建了有輸入?yún)?shù),有輸出參數(shù),有一個(gè)返回記錄集,有一個(gè)返回值的存儲(chǔ)過(guò)程,如下
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
對(duì)于這個(gè)SP來(lái)說(shuō),他這些個(gè)參數(shù)是
@RETURN_VALUE(int ,返回值)
@pin1 ( int ,輸入 )
@pin2 ( char(10) ,輸入 )
@pout1 (int ,輸入/輸出)
@pout1 ( char(10) , 輸入/輸出)
@RETURN_VALUE是第0個(gè)參數(shù),@pin1是第1個(gè),依此類推
以上信息可以在SQL 的查詢分析器中看到,注意,這些參數(shù)的順序很重要
3.調(diào)用的前期準(zhǔn)備
這就不多說(shuō)了,什么import 庫(kù)阿,建立連接阿,什么的,不多說(shuō)了,
這些在 VC中使用ADO進(jìn)行數(shù)據(jù)庫(kù)開(kāi)發(fā)的一些資料的整理 中有了闡述
假定連接是pConn
注意,這里要把pConn設(shè)定成adUseClient型[Page]
pConn->CursorLocation =adUseClient;
下面我要貼具體的代碼了,為了精簡(jiǎn)所貼的代碼,我把所有的捕獲異常都沒(méi)貼出來(lái)(try catch)
4.使用Refresh的方法來(lái)調(diào)用
先定義一些變量
_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參數(shù)賦值
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\");
這個(gè)refresh一定要有,
調(diào)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);
//取記錄集里面的內(nèi)容
if (pRecordset->adoBOF && pRecordset->adoEOF)
{
MessageBox(\"沒(méi)有符合條件的記錄存在!\",\"提示\");
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();
在這里,有一點(diǎn)要注意的是
VretVal = pCmd->Parameters->GetItem(short(4))->Value;
這里的4,就是哪個(gè)output參數(shù)的index,就是我在2中說(shuō)的參數(shù)的順序
這里使用了Refresh,這是一個(gè)很重要的函數(shù),我將在下面介紹一下它,我要先貼出另一種,不使用Refresh的辦法,
5 .使用非Refresh的方法來(lái)調(diào)用
先定義變量
_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來(lái),這里要注意的是,這個(gè)add的順序要和參數(shù)的index順序要一致
下面就是調(diào)用了
pRecordset = pCmd->Execute(NULL,NULL,adCmdStoredProc);
然后取那些return值阿,output值阿什么的
這里有一個(gè)區(qū)別,就是用這種辦法
可以有三種辦法來(lái)取這些返回值和output參數(shù)
VretVal = pCmd->Parameters->GetItem(_bstr_t(\"Return\"))->Value;
VretVal = pCmd->Parameters->GetItem(short(0))->Value;
VretVal = retParam->Value;
都是一樣的
6. 關(guān)于Refresh
關(guān)于這個(gè)函數(shù),作用是
Command 對(duì)象去重新索取要操作的存儲(chǔ)過(guò)程所有有關(guān)參數(shù)的信息,并且清空在refresh之前獲取的參數(shù)信息。
所以一但調(diào)用它以后,就可以獲取SP的那些信息,那些參數(shù)的信息,可以通過(guò)pCmd->Parameters->Item[_variant_t(_bstr_t(\"@pin1\") )]->Value=_variant_t(3); 這樣的方式來(lái)設(shè)置參數(shù)
如果要使用Parameter的辦法的話,就不要用refresh了,事實(shí)上,如果先把這些參數(shù)的值設(shè)置好了,如 inParam2->Value = _variant_t(_T(\"DD1\"));,一旦refresh后,這些參數(shù)就沒(méi)有意義了。
7.關(guān)于pConn->CursorLocation =adUseClient;
設(shè)置這個(gè)東西,如果不設(shè)置游標(biāo)為adUseClient,那么我在取return和output參數(shù)的時(shí)候,必須在我把記錄集關(guān)閉以后才能取,就是說(shuō),必須先取記錄集,然后關(guān)閉它,最后再取return和output參數(shù),如果我在關(guān)閉記錄集之前就取return和output的值,那么就不能取到正確的值,設(shè)成adUseClient就ok了,
另外有一點(diǎn)就是,Execute 方法返回的游標(biāo)繼承該設(shè)置。Recordset 將自動(dòng)從與之關(guān)聯(lián)的連接中繼承該設(shè)置。我把pConn設(shè)成adUseClient,那么最后,我的記錄集也是adUseClient的了[Page]
posted on 2008-06-17 23:39 isabc 閱讀(4273) 評(píng)論(0) 編輯 收藏 引用 所屬分類: 數(shù)據(jù)庫(kù)