1. 程式人生 > >VC++ ADO呼叫儲存過程方法

VC++ ADO呼叫儲存過程方法

一、呼叫基本過程
關於ADO呼叫儲存過程一般是按照以下步驟進行:
1、生成並初始化一個_CommandPtr物件;指定CommandType為儲存過程。
2、生成呼叫儲存過程需要的引數,這些引數都是_ParameterPtr物件;
3、按照順序將使用_CommandPtr的Append方法為儲存過程提供引數(包括輸入引數和輸出引數);
4、為_CommandPtr物件指定需要使用的ADO連線;
5、使用_CommandPtr的Execute方法呼叫儲存過程;
6、從結果中獲取返回引數的值(如果有的話)。

二、儲存過程的輸入/輸出引數
1、建立 _ParameterPtr物件並初始化
        _ParameterPtr pParam;
        pParam.CreateInstance(__uuidof(Parameter));
2、設定_ParameterPtr物件的變數相關引數
     pParam = pCommand->CreateParameter(Name, Type, Direction, Size, Value);
其中Name是引數的名稱,可以指定也可以不指定;
Type是一個DataTypeEnum值,指定引數的類別,取值有adInteger(整型)、adChar(字元/字串型)等;
Direction是一個ParameterDirectionEnum值,其取值為adParamInput、adParamInputOutput、
adParamOutput、adParamReturnValue、adParamUnknown;
Size是一個Long型別的值,指示該引數值以位元組計算的最大長度,例如對int型,該值可以取為sizeof(int),
對Long型,該值可以取為sizeof(long),對字串型,可以使用該字串的長度;
Value是一個variant型別的值,是該引數的取值。
在這裡需要注意的是,Type引數、Direction引數以及Size引數一定要和儲存過程定義時的引數相吻合,
例如,如果有下面一個儲存過程
CREATE PROCEDURE SMS_Proc_Handle_All
(@UserID Integer,
@SourAddr Varchar(15),
@DestAddr varchar(5000),
@AvValue Single output,
@ReturnInfo varchar(100) output
)
則Type引數的取值依次為adInteger、adChar、adChar、adSingle,adChar;
Direction引數的取值依次為adParameterIn、adParameterIn、adParameterIn、adParameterOut、adParameterOut;
對於輸入引數,Size的值可以根據實際數值來定,對於輸出引數,最好是根據定義確定(上例中ReturnInfo引數的Size值可以取為100)。
3、加入到Command物件的引數集屬性中
pCommand->Parameters->Append(< 引數物件名>);
例如:
pCommand->Parameters->Append(pParam);
4、獲取Output的引數
獲取ourput引數是大家最關注的問題,同時也是最“難”的問題,因為按照書本上的寫法,經常獲得不了
Output引數,其實這個問題很容易解決:在呼叫_CommandPtr的Execute方法時,寫成
cmmd->Execute(NULL, NULL, adCmdStoredProc);
這句執行完後,使用
cmmd->Parameters->GetItem("XXXXXX")->GetValue();

輸出引數的名稱,就可以獲得輸出引數的值了。

三、呼叫例項
儲存過程,如下:
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


c++ 呼叫程式碼
_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("sp_1"); //儲存過程名稱
retParam = pCmd ->CreateParameter(_bstr_t("Return"),adInteger,adParamReturnValue,sizeof(int));
pCmd->Parameters->Append(retParam); //這個add的順序要和引數的index順序要一致
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("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);
pRecordset = pCmd->Execute(NULL,NULL,adCmdStoredProc);
//可以用下面兩種辦法來取這些返回值和output引數
VretVal = pCmd->Parameters->GetItem(_bstr_t("Return"))->Value;//通過引數名稱
VretVal = pCmd->Parameters->GetItem(short(0))->Value;//通過引數序號

四、注意事項: 
1、關於Refresh這個函式,作用是Command物件去重新索取要操作的儲存過程所有有關引數的資訊,並且清空在refresh之前獲取的引數資訊。如果是通過pCmd->Parameters來新增引數(存在多個儲存過程使用這個pCmd->Parameters變數),呼叫沒個儲存過程之前呼叫Refresh函式清空已有的引數。
2、關於pConn->CursorLocation =adUseClient;
CursorLocation 屬性,設定或返回遊標引擎的位置。
adUseNone 沒有使用遊標服務。(該常量已過時並且只為了向後相容才出現)。 
adUseClient 使用由本地遊標庫提供的客戶端遊標。本地遊標引擎通常允許使用的許多功能可能是驅動程式提供的遊標無法使用的,因此使用該設定對於那些將要啟用的功能是有好處的。adUseClientBatch 與 adUseClient 同義,也支援向後相容性。 
adUseServer 預設值。使用資料提供者或驅動程式提供的遊標。這些遊標有時非常靈活,對於其他使用者對資料來源所作的更改具有額外的敏感性。但是,Microsoft Client Cursor Provider(如已斷開關聯的記錄集)的某些功能無法由伺服器端遊標模擬,通過該設定將無法使用這些功能。 
說明
該屬性允許在可用於提供者的各種遊標庫中進行選擇。通常,可以選擇使用客戶端遊標庫或位於伺服器上的某個遊標庫。
該屬性設定僅對屬性已經設定後才建立的連線有影響。更改 CursorLocation 屬性不會影響現有的連線。
對於 Connection 或關閉的 Recordset 該屬性為讀/寫,而對開啟的 Recordset 該屬性為只讀。
Connection.Execute 遊標將繼承該設定。Recordset 將自動從與之關聯的連線中繼承該設定。
Remote Data Service用法,當用於客戶端 (ADOR) Recordset 或 Connection 物件時,只能將 CursorLocation 屬性設定為 adUseClient。
3、在呼叫_CommandPtr的Execute方法時,寫成
cmmd->Execute(NULL, NULL, adCmdStoredProc);而不要寫成 RecordsetPtr rec = cmmd->Execute(NULL, NULL, adCmdStoredProc);
如果儲存過程是要取返回的記錄集合的話,可以使用RecordsetPtr rec = cmmd->Execute(NULL, NULL, adCmdStoredProc|adCmdUnspecified);  
4、_CommandPtr中CommandTimeout,表執行超時時間,不設定時預設為30秒。
   _ConnectionPtr中ConnectionTimeout和CommandTimeout分別表示連線超時時間、執行超時時間。
   
參考資料
Microsoft ADO 程式設計師參考 http://www.yesky.com/imagesnew/software/ado/index.html
VC ado呼叫oracle執行儲存過程獲取記錄集 http://blog.csdn.net/imlmy/article/details/8894442