【发布时间】:2018-12-21 23:15:22
【问题描述】:
我希望能够从 MS Access VBA 执行 SQL Server 存储过程,这样我可以读取 (1) 所有结果集,而不仅仅是第一个; (2) PRINT 语句或类似语句产生的任何消息。
我有一个带有一个输入参数的测试存储过程,它产生 3 个不同的结果集和大约 90 条消息。它调用了几个子存储过程,我可以从 SSMS 中很好地执行它,但是(对我来说)不清楚如何最好地从 Access VBA 中执行它。到目前为止,我已经尝试了以下方法:
DAO。使用 SQL 传递查询,我可以在 DAO 中得到很多我想要的东西,尽管它有点笨拙。它将 3 个结果集中的第一个作为记录集返回,通过使用 LogMessages 属性,我可以获得包含发出消息的表(“Admin - NN”)。
ADO。使用 Connection 和 Command 对象,我可以从存储过程中获得表示第一个结果集的单个记录集。但是,我似乎无法说服它生成仅向前的记录集。关于消息,在某一时刻,所有消息(至少,我预期的大约 150 条中的前 127 条)都进入了连接的错误集合(!),但是当我将数量减少到大约 90 条时,它们都没有出现在我能找到的任何地方。
正如我一开始所说,我真正想要的是所有结果集的输出,加上消息。这可能吗?
这是我目前用于执行存储过程的例程列表:
Function ExecuteStoredProcedureADO(SPName As String, Connect As String, ReturnsRecords As Boolean, _
ParamArray Params() As Variant) As ADODB.Recordset
' v1.0 2018/06/26
' execute stored procedure SPName on a SQL Server database specified by the string in Connect
Dim strErr As String
Dim i As Integer
Dim lngRecsAffected As Long
Dim cnn As ADODB.Connection
Dim cmd As ADODB.Command
Dim errCurr As ADODB.Error
Dim rst As ADODB.Recordset
On Error GoTo Catch
Set ExecuteStoredProcedureADO = Nothing
Set cnn = New ADODB.Connection
cnn.Errors.Clear
cnn.mode = adModeRead
cnn.CommandTimeout = 300
cnn.Open Connect
Set cmd = New ADODB.Command
With cmd
.ActiveConnection = cnn
.CommandText = SPName
.CommandType = adCmdStoredProc
For i = 0 To UBound(Params) Step 4
.Parameters.Append .CreateParameter(Params(i), Params(i + 1), adParamInput, Params(i + 2), Params(i + 3))
Next i
Set rst = New ADODB.Recordset
rst.CursorType = adOpenStatic
If ReturnsRecords Then
'''Set rst = .Execute(lngRecsAffected)
rst.Open cmd, , adOpenStatic, adLockReadOnly
Else
Set rst = .Execute(, , adExecuteNoRecords)
End If
End With
If ReturnsRecords Then Set ExecuteStoredProcedureADO = rst
Final:
On Error Resume Next
If Len(strErr) > 0 Then Call AppendMsg(strErr)
Set rst = Nothing
Set cmd = Nothing
Exit Function
Catch:
If cnn.Errors.Count > 0 Then
With cnn
For Each errCurr In cnn.Errors
strErr = strErr & "Error " & errCurr.Number & ": " & errCurr.Description _
& " (" & errCurr.Source & ")" & vbCrLf
Next errCurr
strErr = Left(strErr, Len(strErr) - 2) ' truncate final CRLF
End With
Else
strErr = "Error " & Err.Number & ": " & Err.Description & " (" & Err.Source & ")"
End If
MsgBox strErr, vbOKOnly, gtitle
Resume Final
End Function
附录:关于多个结果集,我希望http://msdn.microsoft.com/en-us/library/ms677569%28VS.85%29.aspx 会有一些帮助。
【问题讨论】:
-
NextRecordSet应该可以正常工作。您只需遍历它们。我从来没有用 SQL Server 过程返回来完成它,但是我已经用从 Teradata 过程返回的 15 个结果集来完成它,它工作得很好。但不确定“消息”。 -
要检索消息,您需要在类中使用 ADO,在类范围内使用
WithEvents声明连接,并使用 Connection_InfoMessage 事件。我会写一个完整的答案,但我目前正在手机上
标签: sql-server ms-access vba ado