MSDN 範例需 CreateParameter、Append、Value 三步驟每參數重複,存儲過程一多維護成噩夢。
_ConnectionPtr pConn(__uuidof(Connection));
pConn->Open(_bstr_t("Provider=SQLOLEDB;Data Source=.;Initial Catalog=Pubs;UID=sa;PWD=;"), L"", L"", adConnectUnspecified);
_RecordsetPtr pRs(__uuidof(Recordset));
// 直接執行「預存程序名 參數1,參數2...」
pRs->Open(_bstr_t("byroyalty 100"), // 等同 EXEC byroyalty 100
_variant_t((IDispatch*)pConn),
adOpenStatic, adLockReadOnly, adCmdText);
// 通用結果集處理
long nFields = pRs->Fields->Count;
while (!pRs->EndOfFile) {
for (long i=0; iFields->GetItem(i);
if (val.vt != VT_NULL) printf("%s ", (char*)_bstr_t(val));
else printf("NULL ");
}
printf("\n");
pRs->MoveNext();
}
pRs->Close();
pConn->Close();
包裝成 T-SQL 批次,將輸出轉為結果集欄位:
// 單一 OUTPUT
DECLARE @q INT;
EXEC checkpwd 'user', 'pwd', @ret = @q OUTPUT;
SELECT @q AS RetCode;
// RETURN + OUTPUT
DECLARE @q INT, @ret INT;
EXEC @ret = checkpwd 'user', 'pwd', @ret = @q OUTPUT;
SELECT @q AS OutParam, @ret AS ReturnVal;
VC++ 端仍呼叫 pRs->Open(sql, ...),結果集自動包含輸出值,**完全不需 CreateParameter**。
EXEC proc @p1, @p2... 位置參數語法。adCmdText 視同普通批次提交,Server 端解析執行。Oracle 需 {call proc(...)} ODBC CALL 語法,但 VC++ 代碼結構完全相同,僅 SQL 字串常數不同。**達成「VC++ 層零修改支援異構資料庫」**。
Integrated Security=SSPI 免密碼。CommandTimeout 設定防止長跑查詢掛死。_com_error 捕獲轉換為自定義例外,記錄 SQL 文本與參數值 (脫敏)。adExecuteStream 或 BULK INSERT。| 維度 | 傳統 Parameter 綁定 | SQL 字串直執行 |
|---|---|---|
| 代碼行數 | O(參數數) | O(1) |
| 預存程序簽名變更影響 | 需同步修改 C++ | 零影響 |
| 型別安全 | 編譯期檢查 | 執行期轉換 |
| SQL 注入風險 | 無 (參數化) | 需自行防範 (參數值嵌入字串) |
| 適用場景 | 核心高頻、型別嚴格 | 報表、管理功能、動態 SQL、異構遷移 |
建議:核心交易路徑用參數綁定,輔助查詢/報表/遷移期用直執行,兩者共存最務實。