Pass progress from multi-step ADO query to VBA using Raiserror: Is this possible?

Pass progress from multi-step ADO query to VBA using Raiserror: Is this possible?

前言

我将此问题具体化以符合 SO 询问指南,但如果您愿意,请随时建议进行全面的重新设计。我可能使用了一些不好的做法。


基本问题

我使用 ADO 执行多步骤 SQL 服务器查询,需要几分钟才能执行。我在我的 tsql 查询中使用 Raiserror 来让自己更详细地知道哪些步骤已经完成。是否可以在完成查询之前将这些消息传递给 VBA,同时继续查询?


详细信息和代码

我使用下面的vba来执行下面的t-SQL查询。如您所见,在显示 "Step 1 complete" 和 "Step 2 complete" 的 t-SQL 中出现了两个错误。我能否将这些消息(或交替使用错误编号并将其传递)传递回 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)

澄清

我不感兴趣:

我不太感兴趣:

研究

我发现的最接近我正在寻找的东西是 here, but as the discussion of that solution 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.

因为我 return 导致我的查询的最后一步在 Excel 中被操纵,所以我认为这对我不起作用。

外部link代码供参考

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) 捕获查询 运行ning 时出现的错误消息。这是要求的方法。

(2) 将大而长的查询分解成几个较小的块,一个接一个 运行。这样您就知道哪一部分已完成,您可以在将下一个块发送到服务器之前根据该信息更新进度条。

(3) 将大而长的查询更新为 log 它在服务器上的临时 table 进度,然后在另一个查询仍在 运行 时读出此日志宁.

虽然我建议仅在发生错误时才使用错误,而不是 "abuse" 它们用于记录、跟踪或反馈,但两个选项(1 和 2)对于 events 都是非常可行的:

Worksheet 事件 Worksheet_ChangeWorksheet_ActivateWorksheet_BeforeDoubleClick 类似,ADODB.Connection 和 [=19] 也有 ADODB 事件=].两者都有很好的记录,并且可以通过以下方式在 VBE 中轻松查看:(1) 添加对 Microsoft ActiveX Data Objects x.x Library 的引用 (2) 按 F2 (3) select 在下拉列表中输入 ADODB 库顶部 (4) 的向下菜单,最后在 类 中查找 RecordsetConnection。以下是 Connection 的可用事件:

如您所见,所有事件都标有闪电。要捕获/使用这些事件,您需要在 VBE 中创建一个 Class Module 并向其中添加以下行:

Dim WithEvents adoConnection As ADODB.Connection

之后,您可以使用新创建的 ADODB.Connection 事件和 select 列表顶部所需的事件:

选项 (1) 的适用事件是 InfoMessage event,它发生在“[...] 每当 ConnectionEvent 操作期间出现警告时。”这里的导入部分是 during a connection。因此,只要 ADODB 连接 "gets" 出错,就会自动触发此事件。

当然,这意味着必须发送对服务器的原始查询,而不等待答复。相反,您应该使用上述事件在查询执行时捕获任何错误,并创建另一个事件以在 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