MSDN 範例需逐一 CreateParameter、Append、設定型別/方向/大小,參數多、業務變動頻繁時維護極其痛苦。
ADO _RecordsetPtr 的 Open 方法接受 SQL 字串,SQL Server 允許 EXEC proc_name param1, param2... 或 proc_name param1, param2... (ODBC CALL 語法) 直接傳遞參數,完全不需建立 Parameter 物件。
_ConnectionPtr pConn(__uuidof(Connection));
pConn->ConnectionString =
"Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DB;User Id=sa;Password=;";
pConn->Open("", "", "", NULL);
_RecordsetPtr pRs(__uuidof(Recordset));
// 1. 一般查詢
pRs->Open("SELECT * FROM Titles", pConn.GetInterfacePtr(), adOpenStatic, adLockReadOnly, adCmdText);
// 2. 呼叫預存程序 (有回傳結果集)
pRs->Open("byroyalty 100", pConn.GetInterfacePtr(), adOpenStatic, adLockReadOnly, adCmdText);
// 等同 EXEC byroyalty 100
// 3. 處理結果集
long nFields = pRs->Fields->GetCount();
while (!pRs->adoEOF) {
for (long i = 0; i < nFields; ++i) {
_variant_t v = pRs->Fields->GetItem((long)i);
if (v.vt != VT_NULL) {
_bstr_t bstr = v;
printf("%s\n", (char*)bstr);
}
}
pRs->MoveNext();
}
pRs->Close();
pConn->Close();
利用 T-SQL 批次將輸出參數轉為結果集:
// 輸出參數 @ret
_bstr_t sql = "DECLARE @q INT EXEC checkpwd 'user','pwd', @ret = @q OUTPUT SELECT @q";
pRs->Open(sql, pConn.GetInterfacePtr(), adOpenStatic, adLockReadOnly, adCmdText);
// 同時取得回傳值與輸出參數
sql = "DECLARE @q INT, @rv INT EXEC @rv = checkpwd 'user','pwd', @ret = @q OUTPUT SELECT @q, @rv";
pRs->Open(sql, pConn.GetInterfacePtr(), adOpenStatic, adLockReadOnly, adCmdText);
相同架構,僅需調整 SQL 文字:
Oracle 匿名區塊 BEGIN proc(:1, :2, :3); END; 或 {CALL proc(?, ?, ?)} (JDBC 風格),ADO 同樣可用文字命令執行。
| 優點 | 缺點/注意 |
|---|---|
| 零 Parameter 物件程式碼,極度簡潔 | 參數值需自行拼接字串,**防 SQL 注入** (建議存數字/安全字串,或改用 Command+Parameter) |
| 動態構建呼叫語句極易 (字串格式化) | 無法直接取得 OUTPUT 參數型別資訊,需約定轉結果集 |
| 除錯容易:複製 SQL 到 SSMS 即可測試 | 大型二進位/長字串參數不適用 |