Solved How to Update a recordset without a loop?

KitaYama

Well-known member
Local time
Tomorrow, 05:09
Joined
Jan 6, 2022
Messages
2,239
If I have a DAO recordset, can I run an update on the recordset to update a field in all records , instead of using a loop and update one record at a time?
Something like an update query, but the object being a recordset instead of a table.

Thanks
 
Solution
Is it possible to write an update query, where the filter for the query is, let's say top 30 last records saved by a specific userFK in a table?
Yes
Code:
UPDATE your_table
SET column_to_update = 'New_value'
WHERE id IN (
    SELECT TOP 30 id
    FROM your_table
    WHERE userFK = 'specific_user_id'
    ORDER BY ID DESC
);
I doubt it. I remember trying it before and got one of those object errors. Since a recordset is derived from an object like a table or a query, I dont think they do not have methods like .Upate

I could be wronf as to the why, but I quite sure it cant be done.

I do not mind being proved wrong!
 
dao does not have a batch update but if you create an ADO recordset it does have a batch update. You still have to loop your records to make the updates then updatebatch.
 
You still have to loop your records to make the updates then updatebatch.
A question just for clarification. If one has to loop through the recordset, how updatebatch can be useful. I mean while looping, a simple line .fields("X")="Y" is enouh.
 
maybe Increase the Lockfiles and use Transaction on your update:
Code:
Dim db As DAO.DBEngine
Const maxDefault& = 9500
Set db = DBEngine
' temporary increase the lock files
db.SetOption dbMaxLocksPerFile, 20000
db.BeginTrans
With rs
    If Not (.BOF And .EOF) Then
        .MoveFirst
    End If
    Do Until .EOF
        .Edit
        'update the field
        !FieldName = "value"
        .Update
        .MoveNext
    Loop
End With
db.CommitTrans
db.SetOption dbMaxLocksPerFile, maxDefault
 
maybe Increase the Lockfiles and use Transaction on your update:
Code:
Dim db As DAO.DBEngine
Const maxDefault& = 9500
Set db = DBEngine
' temporary increase the lock files
db.SetOption dbMaxLocksPerFile, 20000
db.BeginTrans
With rs
    If Not (.BOF And .EOF) Then
        .MoveFirst
    End If
    Do Until .EOF
        .Edit
        'update the field
        !FieldName = "value"
        .Update
        .MoveNext
    Loop
End With
db.CommitTrans
db.SetOption dbMaxLocksPerFile, maxDefault
Transaction is a new world for me. But it's never too late to learn something. I'll try it Monday morning as soon as I'm back to my desk to see if it can be used.

Thanks for your time.
 
If you are look for a all or nothing update, DAO does support transitions. If you have a recordset I presume you know the table and criteria for the selected records, why not write an update query?
 
A question just for clarification. If one has to loop through the recordset, how updatebatch can be useful. I mean while looping, a simple line .fields("X")="Y" is enouh.
In dao you loop the records then make one change then update the table.
In ADO you can loop the records, make all your changes, then update the table.
Code:
' Modify records in memory
Do Until rs.EOF
    rs.Fields("Status").Value = "Processed"
    rs.MoveNext
Loop
' Commit all changes at once
rs.UpdateBatch
 
I had to ask Chat the pros and cons of a bulk update vs a transaction
Here is summary

DAO Transactions vs. ADO Batch Updates​

FeatureDAO TransactionADO Batch Update
PurposeEnsures atomicity across multiple operations (insert/update/delete)Allows editing multiple records in memory before committing
ScopeApplies to any DAO operation (SQL, recordset edits)Applies only to disconnected ADO recordsets
ControlManual: BeginTrans, CommitTrans, RollbackAutomatic: changes cached until UpdateBatch
Error HandlingYou control rollback on failureADO handles conflicts via Filter, Status, or CancelBatch
PerformanceFast for bulk SQL operationsEfficient for client-side editing with fewer round-trips
ConcurrencyDepends on locking mode (dbOptimistic, dbPessimistic)Uses adLockBatchOptimistic for disconnected editing
Use CaseUpdating multiple tables or complex logicUpdating many rows in one table with minimal DB hits


🧩 Summary​

  • DAO transactions are ideal for multi-step logic and SQL-heavy workflows.
  • ADO batch updates shine when you want to edit many rows in memory and push changes in one go.
If you're optimizing for performance or rollback safety in a VBA-heavy environment, DAO transactions give you more granular control. But if you're working with disconnected data or want to minimize DB hits, ADO batch updates are elegant.
Want help deciding which fits better for a specific workflow you're building?
 
If you are look for a all or nothing update, DAO does support transitions. If you have a recordset I presume you know the table and criteria for the selected records, why not write an update query?
I have a continous form that is used for saving new records. Ater a few input, or 20 or more, if a specific condition is met, I have to update a field named "Identifier" of all data which have been saved by this user.

So, the only thing that I have is
Set rs = me.recordsetclone
Then, loop through it to update "Identifier". This causes several flickers (Possibly because of conditional formatting). So actually I know the source table, but don't know the filter to update the source table.
I was thinking if there's a way to do it without a loop, it may help.
I will try @arnelgp's transaction to see if changes the outcome.

Thanks.
 
Wouldn’t that be the userid, perhaps with reference to the condition?
I'm sorry. I don't understand what you're trying to tell me. The same userID may have thousands of records in the table (previous days, previous hours).

A user is handed a 50 order sheets.
He opens a continous form and starts registering data. Let's say while entering the 30th order, a specific condintion based on business rules are met. I have to update a field named "Identifier" for all the 30 saved records. What I'm doing at present is :
Setting a variable to form's recordsetclone, then loop through all records and update it.

I'm not sure if knowing only the userID is enough to update the table, only for these recent records.
Is it possible to run an update query to the source table, with let's say Top 30 records saved by this UserID?
 
If I have a DAO recordset, can I run an update on the recordset to update a field in all records , instead of using a loop and update one record at a time?
Something like an update query, but the object being a recordset instead of a table.

Thanks

I'm going to ask what may be a really stupid question, but... what was the origin of the DAO recordset? Is it a table or query, or did you open a recordset by declaring an SQL SELECT query as a literal string?

If it is any stored query, you should be able to just run an UPDATE query on it. Therefore, I have to assume that you don't have it as a stored object. But you can use the DB.Execute syntax to take a variant of that string to do an update query on-the-fly - if you can specify the selection of records to be updated. From your description, you are done with the recordset at the point where you are ready for the update, so there is no issue with having to requery the recordset after the update - just close things and be done with it.

This is a case where if I know ahead of time that after a series of recordset operations I will have some bulk UPDATE operations related to that recordset, I will prepare ahead of time to do both things in the order necessary for the business process.
 
what was the origin of the DAO recordset? Is it a table or query, or did you open a recordset by declaring an SQL SELECT query as a literal string?
The recordset is :
Set rs=Me.RecordsetClone

It's a copy of the recordset of the form opened for user to work on.


I will prepare ahead of time to do both things in the order necessary for the business process.
The only way to be prepared, is to check all the order sheets one by one to see if the contents are met with a business rule.
I can not ask someone to check all sheets at the start of the day.

Thanks.
 
Lets say you open a form and the user then applies filters and modifies it. One thing I do often do in that case especially if they have created a complex filter and it is based on a complex query is to figure out the PKs of the records that are still in the form and meet the criteria.

Code:
Public Function GetPK_Criteria(PK_FieldName As String, Frm As Access.Form)
  Dim fltr As String
  Dim I As Long
  Dim val As Long
  Dim rs As DAO.Recordset
  'Provide a column number if not using the bound column
  Set rs = Frm.RecordsetClone
  If Not rs.EOF Then rs.MoveFirst
  Do While Not rs.EOF
    val = rs.Fields(PK_FieldName)
    If fltr = "" Then
      fltr = val
    Else
      fltr = fltr & ", " & val
    End If
    rs.MoveNext
  Loop

  If fltr <> "" Then
    fltr = " IN (" & fltr & ")"
  End If
  GetPK_Criteria = fltr
End Function

Now if we are talking thousands of records you could hit the limits of a SQL string.

But in the above if you pass the form and the name of the PK field it produces something like
Code:
IN (1, 2, 3, 4, 17, 18, 39, 40, 60)

Then you can create your update
Code:
dim Criteria as string
criteria = GetPK_Criteria("ProductID", Me)
StrSql
dim Criteria as string
criteria = GetPK_Criteria("ProductID", Me)
StrSql = "Update table1 set somefield = "X" where SomePK " & Criteria
= "Update table1 set somefield = "X" where SomePK " & Criteria
Currentdb.execute strSql

So the IN string are all the PKs still on the form. But you could add more criteria if necessary
Code:
dim Criteria as string
criteria = GetPK_Criteria("ProductID", Me)
Criteria = Criteria & " AND Status = 'Current'"
 
One more thing. Even without any of these other methods, simply try turning echo off and then back on.
When looping through a DAO recordset in Access, it's smart to turn off screen updates using to reduce flickering and improve performance—especially if you're updating forms, controls, or triggering UI refreshes indirect
Here is the double safe construct with both a transaction and with echo off. My guess is just one of these is good enough.

Code:
Sub UpdateRecords()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset

    On Error GoTo Cleanup
    Application.Echo False
    Set db = CurrentDb
    Set rs = db.OpenRecordset("SELECT * FROM MyTable", dbOpenDynaset)

    db.BeginTrans
    Do While Not rs.EOF
        rs.Edit
        rs!SomeField = "NewValue"
        rs.Update
        rs.MoveNext
    Loop
    db.CommitTrans

Cleanup:
    If Application.Echo = False Then Application.Echo True
    If Not rs Is Nothing Then rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub
Make sure that you turn echo on in the error handler
 
Lets say you open a form and the user then applies filters and modifies it. One thing I do often do in that case especially if they have created a complex filter and it is based on a complex query
Unfortunately it's not a filtered form, but a form with Data Entry set to Yes.
I'm actually using the method you explained in other forms.
For this specific situation, I was trying to find a way not to work on the recordsetClone of the form, specially in a loop (Because of screen flickerings)
But the moethod you explaind, doesn't update RecorsetClone, only reading the PK of table.
I'll give it a try to see if it prevents the flickerings.

One question:
Is it possible to write an update query, where the filter for the query is, let's say top 30 last records saved by a specific userFK in a table?
I'm not good in sub queries and I'm not sure if it's possible at all.
If it's possible, I think I can use it without touching the form's recordset.

Thanks
 
You can't use TOP with an update query but if you know the recordPK of the first record entered you could use something like this (not tested)

Code:
with recordsetclone
    .movefirst
    currentdb.execute "UPDATE myTable SET identifier="something" WHERE UserFK=" & !userFK & " and recordPK>=" & !recordPK
end with
 
But the moethod you explaind, doesn't update RecorsetClone, only reading the PK of table.
I'll give it a try to see if it prevents the flickerings.
It is not reading the PKs of the table it is reading the PKs of the records in the forms recordset. This can be a filtered or queried set of records.

Yes it does not update the recordset clone, but it updates all the records contained in the recordset clone. So depending on what you are doing that may give equivalent results.
 

Users who are viewing this thread

Back
Top Bottom