前言
我提出这个问题是为了符合 SO 询问指南,但如果您愿意,请随时建议批发重新设计。我可能正在使用一些不好的做法。
基本问题
我使用 ADO 执行需要几分钟才能执行的多步骤 SQL Server 查询。我用 Raiserror
在我的 tsql 查询中让自己更详细地知道哪些步骤已经完成。是否可以在完整查询完成之前将这些消息传递给 VBA,同时仍继续查询?
详细信息和代码
我使用下面的 vba 来执行下面的 t-SQL 查询。如您所见,t-SQL 中出现了两个错误,分别显示“步骤 1 完成”和“步骤 2 完成”。我可以将这些消息(或交替使用错误号并将它们传递)以一种允许我检测它们并在继续执行查询的同时更新进度条的方式传递回 VBA 吗?
用于执行查询的 VBA:
Set cmd = New ADODB.Command
cmd.ActiveConnection = cnn
cmd.CommandTimeout = 0
cmd.CommandText = strQuery
Set rst = New ADODB.Recordset
rst.Open cmd
'Go to the second to last recordset of the multi-step query
String1 = Replace(strQuery, ";", "")
For Loop2 = 1 To (Len(strQuery) - (Len(String1) + 1))
Set rst = rst.NextRecordset
Next Loop2
'Copy results
If Not rst.EOF Then
(snip - actions)
Else
MsgBox "Error: No records returned."
End If
精简的多步 tSQL 查询:
--#DRS1: The numbers being researched
select distinct numbers
into #DRS1
from Table1 (nolock)
where numbers in ()
--#DRS1: Index
create nonclustered index Idx_DRS1
on #DRS1(numbers);
Raiserror(“Step 1 complete”,1,1) with nowait;
--#DRS2: Table2 for numbers being researched
select distinct
DRS1.numbers
,a.ID
into #DRS2
from #DRS1 DRS1
join Table2 (nolock) a
on DRS1.numbers = a.numbers
Raiserror(“Step 2 complete”,1,1) with nowait;
--MORE STEPS
(more steps)
(more raiserror statements)
澄清
我对以下内容不感兴趣:
Progress
的方法/MaxProgress
,因为据我了解,这将为查询中的每个步骤返回单独的数字,而不是为整个查询返回一个进度度量。 我不太感兴趣:
# records affected
消息来确定进度,因为某些步骤可能会返回与先前步骤相同数量的记录。 研究
我找到的最接近我正在寻找的东西是 here ,但作为该解决方案的讨论here说:
This approach would only work for stored procedures that are not intended to return results, say procs that insert data into tables. Another approach would be needed if your stored proc returns a result set.
由于我在查询的最后一步返回结果,以便在 Excel 中进行操作,我认为这对我不起作用。
外部链接代码供引用
SQL:
CREATE PROCEDURE dbo.updTesting As
Declare @RetVal integer
Exec @RetVal = updTesting2
Return @RetVal
GO
CREATE PROCEDURE dbo.updTesting2 As
raiserror('Error From Testing 2 procedure',16,1)
Return -2
GO
VBA:
Private Sub Command1_Click()
On Error GoTo ErrorHandler
Dim db As ADODB.Connection
Dim cmd As ADODB.Command
Set db = New ADODB.Connection
db.CursorLocation = adUseClient
db.Open "provider=sqloledb;data source=handel;initial catalog=northwind;integrated security=sspi"
Set cmd = New ADODB.Command
With cmd
Set .ActiveConnection = db
.CommandText = "updTesting"
.CommandType = adCmdStoredProc
.Parameters.Append .CreateParameter("@RetVal", adInteger, adParamReturnValue)
.Execute , , adExecuteNoRecords
End With
ExitPoint:
On Error Resume Next
Set cmd.ActiveConnection = Nothing
Set cmd = Nothing
db.Close
Set db = Nothing
Exit Sub
ErrorHandler:
MsgBox "Error # " & Err.Number & vbNewLine & vbNewLine & Err.Description
Resume ExitPoint
End Sub
最佳答案
有几种可能性可以为您的问题制定解决方案:
(1) 在查询运行时捕获错误消息。这就是要求的方法。
(2) 将大而长的查询分解成几个较小的 block 并一个接一个地运行它们。像这样,您知道哪个部分已完成,并且您可以在将下一个 block 发送到服务器之前根据该信息更新进度条。
(3) 将大而长的查询更新为 log
它在临时表中的服务器上的进度,然后在另一个查询仍在运行时读出此日志。
虽然我建议仅在发生错误时才使用错误,而不是“滥用”它们进行日志记录、跟踪或反馈,但两个选项(1 和 2)对于 events
来说都是非常可行的。 :
类似于 Worksheet
事件 Worksheet_Change
, Worksheet_Activate
, 或 Worksheet_BeforeDoubleClick
还有ADODB
ADODB.Connection
的事件和 ADODB.Recordset
.两者都有很好的文档,可以通过 (1) 添加对 Microsoft ActiveX Data Objects x.x Library
的引用在 VBE 中轻松查看。 (2) 按F2
(3)在顶部下拉菜单中选择ADODB库(4)最后查找Recordset
或 Connection
类内。以下是 Connection
的可用事件:
如您所见,所有事件都标有闪电。要捕获/使用这些事件,您需要创建 Class Module
在 VBE 中添加以下行:
Dim WithEvents adoConnection As ADODB.Connection
之后,您可以使用新创建的
ADODB.Connection
事件并从列表顶部选择所需的事件:选项 (1) 的适用事件是 InfoMessage event每当在 ConnectionEvent 操作期间发生警告时,就会发生“[...]”。这里的导入部分是在期间一个连接。因此,只要 ADODB 连接“遇到”错误,此事件就会自动触发。
当然,这意味着必须向服务器发送原始查询 没有 等待答案。相反,您应该使用上述事件在查询执行时捕获任何错误,并创建另一个事件以在 entire query completed 时自动触发。 .
有关异步 ADODB 连接的更多帮助以及它们可能存在的问题,您可能希望在此处查看以下两篇文章:
ExecuteComplete ADODB Connection event not fired with adAsyncExecute parameter
Running multiple async queries with ADODB - callbacks not always firing
类似的方法可以与上述选项 (3) 和异步 ADODB 连接一起使用。
让我知道这是否解决了您的问题或您有任何其他问题。
全部可用
ADODB
事件可以在这里查看 https://msdn.microsoft.com/en-us/library/ms675083%28v=vs.85%29.aspx
关于excel - 使用 Raiserror : Is this possible? 将多步 ADO 查询的进度传递到 VBA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37057191/