ASP 經典開發中,通過 ADO 調用存儲過程主要有三類場景:純執行(INSERT/UPDATE/DELETE)、返回記錄集(SELECT)、返回輸出參數/返回值。本文給出標準代碼模板、參數創建細節與常見錯誤避坑指南。
適用於 INSERT/UPDATE/DELETE,僅需輸入參數。
<%
' 方法 1:Connection.Execute(最簡潔,適合少參數)
conn.Execute "usp_InsertOrder @CustID=1001, @Amount=299.5"
' 方法 2:Command 對象(參數化、類型安全、復用計畫)
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = "usp_InsertOrder"
.CommandType = 4 ' adCmdStoredProc
.Parameters.Append .CreateParameter("@CustID", 3, 1, , 1001) ' adInteger, adParamInput
.Parameters.Append .CreateParameter("@Amount", 5, 1, , 299.5) ' adDouble
.Execute
End With
%>
<%
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = "usp_GetOrderDetail"
.CommandType = 4
.Parameters.Append .CreateParameter("@OrderID", 3, 1, , 8888)
End With
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient (斷開連接後仍可操作)
rs.Open cmd, , 0, 1 ' adOpenForwardOnly, adLockReadOnly
' 處理 rs...
rs.Close
Set rs = Nothing
%>
關鍵點:CursorLocation = adUseClient 將游標移至客戶端,釋放服務器資源,支援斷開連接後操作 Recordset。
存儲過程定義:
CREATE PROC usp_CalcOrderTotal
@OrderID INT,
@TotalAmount MONEY OUTPUT,
@ItemCount INT OUTPUT
AS
SELECT @TotalAmount = SUM(Amount), @ItemCount = COUNT(*)
FROM OrderItems WHERE OrderID = @OrderID
RETURN 0 -- 返回值(整數),通常用於狀態碼
ASP 調用:
<%
Set cmd = Server.CreateObject("ADODB.Command")
With cmd
.ActiveConnection = conn
.CommandText = "usp_CalcOrderTotal"
.CommandType = 4
.Parameters.Append .CreateParameter("@OrderID", 3, 1, , 8888) ' Input
.Parameters.Append .CreateParameter("@TotalAmount", 6, 2, , 0) ' adCurrency, adParamOutput
.Parameters.Append .CreateParameter("@ItemCount", 3, 2, , 0) ' adInteger, adParamOutput
.Parameters.Append .CreateParameter("@ReturnVal", 3, 4, , 0) ' adInteger, adParamReturnValue
.Execute
End With
Dim total, cnt, ret
total = cmd.Parameters("@TotalAmount").Value
cnt = cmd.Parameters("@ItemCount").Value
ret = cmd.Parameters("@ReturnVal").Value
' total, cnt, ret 即為輸出結果
%>
.CreateParameter(Name, Type, Direction, Size, Value)
' Type 常用常量:
' 3 = adInteger
' 5 = adDouble
' 6 = adCurrency (MONEY)
' 200 = adVarChar
' 201 = adLongVarChar (TEXT/NTEXT)
' 135 = adDateTime
' Direction:
' 1 = adParamInput (默認)
' 2 = adParamOutput
' 3 = adParamInputOutput
' 4 = adParamReturnValue
| 錯誤現象 | 原因 | 修正 |
|---|---|---|
| 「參數數量不匹配」 | 調用時未按順序/名稱提供所有 INPUT/OUTPUT 參數 | 用 .NamedParameters = True 並按名稱追加,或嚴格按定義順序追加 |
| OUTPUT 參數值為空/錯誤 | 未指定 Direction = adParamOutput 或 Size 不足 | 顯式設定 Direction,字符類型 Size 需 ≥ 定義長度 |
| 返回值無法獲取 | 未追加 adParamReturnValue 參數,或未在存儲過程 RETURN @val | 追加 ReturnValue 參數,存儲過程用 RETURN 而非 SELECT |
| 記錄集關閉後無法讀取字段 | 用默認服務器端游標,連接關閉導致失效 | 設置 rs.CursorLocation = adUseClient |
| 併發下參數值錯亂 | 全局 Command/Connection 對象被多線程共用 | 每請求創建獨立 Command/Connection,用完即銷毀 |
Function ExecProc(procName, paramsArray, Optional needRecordset = False)
' paramsArray = Array(Array("@p1", 3, 1, , val1), Array("@p2", 6, 2, , 0), ...)
Dim cmd, rs, i, p
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = conn
cmd.CommandText = procName
cmd.CommandType = 4
cmd.NamedParameters = True
For i = 0 To UBound(paramsArray)
p = paramsArray(i)
cmd.Parameters.Append cmd.CreateParameter(p(0), p(1), p(2), p(3), p(4))
Next
If needRecordset Then
Set rs = Server.CreateObject("ADODB.Recordset")
rs.CursorLocation = 3
rs.Open cmd, , 0, 1
Set ExecProc = rs
Else
cmd.Execute
Set ExecProc = cmd.Parameters ' 返回參數集合供取值
End If
End Function