【问题标题】:VBA - 运行插入语句返回 rowsAffected = 1 但实际上并未将任何行插入表中。语句在 SQL Server 中工作正常
【发布时间】:2022-01-23 08:10:16
【问题描述】:

问题: 通过 VBA 运行的插入语句返回 rowsAffected = 1,但是在该表上运行选择语句时,它不会显示任何新行。通过 SQL Server 运行完全相同的插入语句可以按预期工作,所以我知道问题不是语句本身。

我创建了一个电子表格,我的同事可以在其中将一些数据输入到列中,我的 VBA 将确定哪些数据需要更新到我们的服务器中。我在使用INSERT 语句时遇到问题,但是我的UPDATE 语句运行良好。

下面是我正在运行的代码。它首先运行UPDATE 查询,如果rowsAffected 返回0,那么它会获取相应的INSERT 语句并尝试运行它。在此子例程运行之前,我有另一个子例程创建所有UPDATE 查询和所有INSERT 查询并将它们存储在传递给以下子例程的集合中。

Private Sub sqlQueryNotes(queries As Collection, iQueries As Collection)
    'queries collection stores all of the UPDATE queries
    'iQueries collection stores all of the INSERT queries    

Dim rAffected As Integer
Dim cn As Adodb.Connection
Set cn = New Adodb.Connection

Dim cString As String
    cString = "Provider=MSOLEDBSQL;" & _
                       "Server=[SERVERNAME];" & _
                       "Database=[DATABASENAME];" & _
                       "Trusted_Connection=yes;"

cn.connectionString = cString
cn.Open

Dim i As Integer
For i = 1 To queries.Count

    cn.Execute "Begin Tran " & queries.Item(i), rAffected 'UPDATE statement
    
    If rAffected = 0 Then
                       
            'below code looks a bit messy but it works, it finds the contractID from the update query and uses that as a key for the insertQuery key to find the corresponding insert query. It could be done better, but it works
            cn.Execute "Begin Tran " & iQueries.Item(getContractID(queries.Item(i))), rAffected 
            
            If rAffected > 1 Then
                cn.Execute "Rollback"
                GoTo NextQuery
            ElseIf rAffected = 0 Then
                GoTo NextQuery
            Else
                cn.Execute "Commit"
                GoTo NextQuery
            End If
        
    ElseIf rAffected = 1 Then
        
        cn.Execute "Commit "
    
    End If
    
NextQuery:
Next i

cn.Close
Set cn = Nothing

End Sub

我已经对此进行了数十次测试,每次都单独遍历每一行并手动检查rowsAffected 变量,以确认它实际上已插入了我想要的数据(通过返回值1)。这段代码确实按照预期的方式工作,当我运行 INSERT 语句时,我确实得到了 rowsAffected = 1

但是,当我为要插入的表运行SELECT 语句时,它不会返回新行!

我已使用我的 VBA 代码生成的 INSERT 语句,并通过 SQL Server 运行它们,它们工作正常。那么为什么它不能通过我的 VBA 代码运行呢?

如果相关,下面是我运行以生成UPDATE 语句和INSERT 语句的代码。为了简洁起见,我删除了很多不相关的行

Sub UpdateBackendDatabase()

    Dim ws As Worksheet
    Dim updNoteCol As Integer: updNoteCol = Range("_" & Replace(Left(ws.Name, 6), " ", vbNullString) & "_uNotes").Column
    Dim refNoteCol As Integer: refNoteCol = updNoteCol - 1
    
    Dim contractIdCol As Integer: contractIdCol = Range("_" & Replace(Left(ws.Name, 6), " ", vbNullString) & "_contractId").Column
    Dim contractID As String
    
    Dim tbl As Range
    Set tbl = ws.Range("tblReporting_" & Replace(Left(ws.Name, 6), " ", vbNullString))
    
    Dim notesQueriesColl As New Collection
    Dim insCollection As New Collection
    
    Dim updateQry As String
    Dim insertQry As String

    'Loop through all rows in table and find values that have been updates and add them to a query and add the queries to a collection of queries.
    Dim i As Integer
    For i = 3 To Range("tblReporting_" & Replace(Left(ws.Name, 6), " ", vbNullString)).Rows.Count + 2
    
        contractID = tbl.Cells(i, contractIdCol).Value
       
        '===============
        '==== NOTES ====
        '===============
        If tbl.Cells(i, updNoteCol).Value <> vbNullString Then
                'grabs notes from the refNoteCol and concats it with new additional notes from the updNotesCol
            updateQry = "Update tblCMNotes " & _
                            "Set strNotes = '" & tbl.Cells(i, refNoteCol) & "; " & Format(Date, "dd/mm/yyyy") & " - " & tbl.Cells(i, updNoteCol).Value & "' " & _
                            "Where fkidContract = " & CStr(contractID)
            
            insertQry = "Insert Into tblCMNotes " & _
                        "(fkidContract, strNotes) " & _
                        "Values " & _
                        "(" & contractID & ", '" & tbl.Cells(i, refNoteCol) & "; " & Format(Date, "dd/mm/yyyy") & " - " & tbl.Cells(i, updNoteCol).Value & "') "
            
            notesQueriesColl.Add updateQry
            insCollection.Add insertQry, getContractID(updateQry)

        End If
            
    Next i
    
    Set ws = Nothing

End Sub

非常感谢您调查这个问题。

【问题讨论】:

  • 我不是 SQL Server 用户,但您不是每次循环迭代都开始两个事务(如果第一个 rAffected = 0),而不是同时关闭它们吗?
  • 可能更简单地组合更新/插入命令,如 Evgeny 所示:stackoverflow.com/a/15396779/478884
  • 提供程序特定的命令文本“Commit”或“Commit”是 SQL 服务器命令。您可能应该使用 ADODB 方法 committrans

标签: sql-server vba


【解决方案1】:

提供程序特定的命令文本“Commit”或“Commit”是 SQL 服务器命令。您可能应该使用 ADODB 方法 committran

【讨论】:

    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多