问题
I've created a table in a SQL Server 2017 database. Then I've created a form in MS Access 2019 that use an ADO Object as "record source". On the form, there is a Textbox with the controlsource property=Field. Then, when I open the form, everything works as expected (the content of Field shows up in the Textbox, I can move the cursor backwards and forwards and so on) except for one thing: It's not possible to change, add or delete records.
Create a table On SQL Server (use SSMS):
CREATE TABLE Table1 (Field INT PRIMARY KEY)
INSERT INTO Table1 (Field) VALUES (15)
INSERT INTO Table1 (Field) VALUES (12)
In Access Module:
#Const EarlyBinding = -1
#If EarlyBinding Then
' Irrelevant in this context
#Else
Global Const adUseClient As Long = 3
Global Const adLockBatchOptimistic As Long = 4
Global Const adOpenDynamic As Long = 2
#End If
In Access Form's VBA Code:
Private Sub Form_Load()
Dim sqldb as Object, adocom as Object, rs As Object
Set sqldb = CreateObject("ADODB.Connection")
Set adocom = CreateObject("ADODB.Command")
Set rs = CreateObject("ADODB.Recordset")
SQLDB.Open "Driver={SQL Server Native Client 11.0};Server=SQL;Database=Test;Trusted_Connection=yes;"
SQLDB.CursorLocation = adUseClient
rs.LockType = adLockBatchOptimistic
rs.CursorType = adOpenDynamic
adocom.CommandText = "SELECT Field FROM Table1"
set rs = adcom.execute
set Me.Recordset=rs
end sub
This problem is "boiled down" from a much more complex code. The query I pass to SQL Server takes several minutes to execute if I use DAO so the big point is to let SQL Server execute the query (takes < 1 sek).
So what do I have to do to make it possible to add, modify or delete a record?
DML commands like
adocom.execute ”UPDATE Table1 SET Field=25 WHERE Field=15”
works.
But well, the thing is, I want the Access Form to act in exactly the same way with an ADO recordset connected to a SQL Server as it would act if the recordset was handled by a DAO object connected to a backend .accdb-file. So it’s the recordset that should be updatable. The property rs.recordcount is -1 which indicates that the recordset is not updatable. If that property is something else but -1 after the adocom.execute line , then we’re home.
回答1:
Seems like the .Execute method returns read-only, forward-only cursor recordset.
You have to use theRecordset.Open
method to get a not read-only Recordset.
This works for me:
Private Sub Form_Load()
Dim sqldb As Object, adocom As Object, rs As Object
Set sqldb = CreateObject("ADODB.Connection")
Set adocom = CreateObject("ADODB.Command")
Set rs = CreateObject("ADODB.Recordset")
sqldb.Open "Driver={SQL Server Native Client 11.0};Server=SQL;Database=Test;Trusted_Connection=yes;"
sqldb.CursorLocation = adUseClient
rs.LockType = adLockBatchOptimistic
rs.CursorType = adOpenDynamic
rs.Open "SELECT Field FROM Table1", sqldb 'changed code
Set Me.Recordset = rs
End Sub
As I told you in my comment above, you should always check the settings of the recordset in locals windows, as they may differ from what you have set!
In your code, the recordsets.LockType
getsadLockReadOnly
, what explains read-only form.
Btw, your code looks like using late-boundADODB
, but usesADODB-Constants
likeadUseClient
. They need to be defined seperate if you use late-boundADODB
来源:https://stackoverflow.com/questions/58231999/ms-access-2019-sql-server-2017-recordset-cannot-be-updated