【问题标题】:How to find the result of an ADO Query in MS Access如何在 MS Access 中查找 ADO 查询的结果
【发布时间】:2021-01-11 10:22:09
【问题描述】:

MS Access 2019 SQL Server 2017

在 VBA 代码中是否有任何直接、简单的方法来确定此查询是否导致提交或回滚。

这不是不可解决的,但我正在寻找一种不太复杂的方法。

在 MS Access 模块中:

  Dim SQLDB As Object
  Dim ADOcom As Object
  Dim sql As String

  sql = _
    "BEGIN TRY " & _
    "  BEGIN TRAN " & _
    "    UPDATE MyTable SET MyColumn=100 WHERE AnotherColumn=5 " & _
    "  COMMIT TRAN " & _
    "END TRY " & _
    "" & _
    "BEGIN CATCH " & _
    "  ROLLBACK TRAN " & _
    "END CATCH"
  
  Set SQLDB = CreateObject("ADODB.Connection")
  Set ADOcom = CreateObject("ADODB.Command")
  SQLDB.Open "Driver={SQL Server Native Client 11.0};Server=SQL;Database=MyDatabase;Trusted_Connection=yes;"
  SQLDB.CursorLocation = adUseClient
  Set ADOcom.activeconnection = SQLDB
  With ADOcom
    .CommandText = sql
    .Execute sql

' Code to find out if the .execute resulted in Commit

  End With
  Set ADOcom = Nothing
  SQLDB.Close
End Sub

完成: 在此示例中,两个查询从任意 MS Access 模块发送到任意 SQL Server。 第一个查询返回预期值,但第二个查询不返回。 这两个查询在 SSMS 中都能正常工作。 第二个查询有什么问题?

Sub Example()
  Dim SQLDB As Object
  Dim query_1 As String, query_2 As String
  Dim rs As Object
  
  Set SQLDB = CreateObject("ADODB.Connection")
  SQLDB.Open "Driver={SQL Server Native Client 11.0};Server=MySQLserver;Database=MyDatabase;Trusted_Connection=yes;"
  Set rs = CreateObject("ADODB.Recordset")
  Set rs.activeconnection = SQLDB
  
  query_1 = _
    "SELECT 1"
  
  rs.Open query_1
  Debug.Print rs(0) ' Expected 1, got 1.
  rs.Close
  
  query_2 = _
    "DECLARE @Success INT " & _
    "BEGIN TRY " & _
    "  BEGIN TRAN " & _
    "    SELECT 1/0 " & _
    "    SET @Success=1 " & _
    "  COMMIT TRAN " & _
    "END TRY" & _
    " " & _
    "BEGIN CATCH " & _
    "  ROLLBACK TRAN " & _
    "  SET @Success=0 " & _
    "END CATCH " & _
    "SELECT @Success AS [Success]"

  rs.Open query_2
  Debug.Print rs(0) ' Expected 0 but rs is Nothing and got Error 3265
  rs.Close
  
  SQLDB.Close
End Sub

【问题讨论】:

  • 在您调用rollback 之后,只需再次调用 throw 并在您的代码异常处理程序中捕获它。
  • @andarvi 你能访问这样的值吗rs.Fields(0).Value
  • 不,rs.Fields.Count 为 0,rs 为空。

标签: sql-server vba tsql error-handling ms-access-2016


【解决方案1】:

您可以返回status 值或@variable。例如,

  sql = _
    "BEGIN TRY " & _
    "  BEGIN TRAN " & _
    "    UPDATE MyTable SET MyColumn=100 WHERE AnotherColumn=5 " & _
    "    SELECT 0 AS [ErrorStatus] " & _
    "  COMMIT TRAN " & _
    "END TRY " & _
    "" & _
    "BEGIN CATCH " & _
    "  ROLLBACK TRAN " & _
    "  SELECT 1 AS [ErrorStatus] " & _
    "END CATCH"

您可以在以下代码中使用此结果。在CATCH 中,您可以使用THROW 来获取原始错误并仍然使事务回滚:

BEGIN CATCH
      ROLLBACK TRAN;
      THROW;
END CATCH

这意味着您需要在 vb.code 本身中有一个 try/catch。如果您需要错误详细信息,另一种方法是使用以下函数(在 SSMS 中执行):

BEGIN TRY  
    -- Generate a divide-by-zero error.  
    SELECT 1/0;  
END TRY  
BEGIN CATCH  
    SELECT  
        ERROR_NUMBER() AS ErrorNumber  
        ,ERROR_SEVERITY() AS ErrorSeverity  
        ,ERROR_STATE() AS ErrorState  
        ,ERROR_PROCEDURE() AS ErrorProcedure  
        ,ERROR_LINE() AS ErrorLine  
        ,ERROR_MESSAGE() AS ErrorMessage;  
END CATCH;  
GO

他们正在返回错误的详细信息。您可以将它们返回或将它们分配给变量并稍后处理。

【讨论】:

  • 谢谢,但是如何在 VBA 代码中达到从 SQL Server 返回的 Status 值 [ErrorStatus]?我正在寻找类似if Errorstatus=0 then debug.print "Ok" else debug.print "Failed"
  • 很抱歉,该代码不起作用。如果我像您在示例中所做的那样使用SELECT 0 AS [ErrorStatus]SELECT 1 AS [ErrorStatus] 完成查询,则不会向rs 返回任何内容。没有错误,但 rs.Fields.Count 为 0,因此列 [ErrorStatus] 根本不存在于 rs 中。这就是这种情况下的大问题:在 VBA 环境中无法确定 TSQL 事务是否成功。
  • 附言。如果传递给 SQL Server 的查询包含 DQL 以外的其他命令,则 rs 似乎为空。如果查询仅包含 DQL 命令,您建议的代码可以正常工作。
  • 我不知道该怎么做,因为这个评论字段太短了。
【解决方案2】:

我想我找到了这个问题(错误?)的解决方案(变通方法)。

如果在 query_2 中添加SET NOCOUNT ON 作为第一条语句,它会突然起作用。我不知道为什么,但这是事实。

Sub Example()
  Dim SQLDB As Object
  Dim query_1 As String, query_2 As String
  Dim rs As Object
  
  Set SQLDB = CreateObject("ADODB.Connection")
  SQLDB.Open "Driver={SQL Server Native Client 11.0};Server=MySQLserver;Database=MyDatabase;Trusted_Connection=yes;"
  Set rs = CreateObject("ADODB.Recordset")
  Set rs.activeconnection = SQLDB
  
  query_1 = _
    "SELECT 1"
  
  rs.Open query_1
  Debug.Print rs(0) ' Expected 1, got 1.
  rs.Close
  
  query_2 = _
    "SET NOCOUNT ON " & _
    "DECLARE @Success INT " & _
    "BEGIN TRY " & _
    "  BEGIN TRAN " & _
    "    SELECT 1/0 " & _
    "    SET @Success=1 " & _
    "  COMMIT TRAN " & _
    "END TRY" & _
    " " & _
    "BEGIN CATCH " & _
    "  ROLLBACK TRAN " & _
    "  SET @Success=0 " & _
    "END CATCH " & _
    "SELECT @Success AS [Success]"

  rs.Open query_2
  Debug.Print rs(0) ' Expected 0, got 0.
  rs.Close
  
  SQLDB.Close
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多