【发布时间】: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