问题
I have a form that performs a search query on table A
, which outputs the result on a subform on the same form.
What I want to do is to add in a button that will move selected records on the subform into table B
, deletes the records from table A
(which I assume will be similar in principle to what I want to do below), then requeries the search, which I assume can be done with something as simple as me.requery
.
strID = Me.Form1_subform.Form.ID.Value
strSQL = "INSERT INTO B ([a], [b], [c]) "
strSQL = strSQL + "SELECT [a], [b], [c] "
strSQL = strSQL + "From A"
strSQL = strSQL + "WHERE [ID] = " & strID
DoCmd.RunSQL strSQL
The above is my attempt to insert records from A
into B
. Right now, the above code only performs the operation on the first of many selected records (it works as expected, but I can't seem to find out how to get Access to recognize that other records are being selected). Is there a simple way of performing a loop of the above code in Access? I am currently only able to get Access to work with the topmost selected record, and that is not something I can really work with.
Furthermore, the above code retains the primary key value (ID) when moved into table B
. Is there a way to prevent this?
回答1:
If your tables A
and B
have the same columns for records filtering, you can just use WHERE
clause used for searching rows in A
table. But in some cases it may be difficult, especially if user is able to filter the subform manually. In this case you can create WHERE clause like this:
WHERE [ID] in (1,3,5,7....)
If there are a lot of rows in the subform, this SQL may exceed SQL string length limit, so it's reasonable to split the moving into few chunks:
Dim lngCounter As Long
Dim rst As DAO.Recordset
Dim strWhere As String
Dim strSQL As String
Const lngChunkSize = 100
Set rst = Me.RecordsetClone
If rst.RecordCount > 0 Then
rst.MoveFirst
Do Until rst.EOF
lngCounter = lngCounter + 1
'Collect keys
strWhere = strWhere & rst!ID & ","
rst.MoveNext
If lngCounter Mod lngChunkSize = 0 Or rst.EOF Then
'chunk is full or end operations, move rows
strWhere = Left(strWhere, Len(strWhere) - 1) 'remove last coma
strSQL = "INSERT INTO B ([a], [b], [c]) " & _
"SELECT [a], [b], [c] From A where ID in (" & strWhere & ")"
'use ADO, it supports longer strings
CurrentProject.Connection.Execute strSQL
strSQL = "DELETE * From A where ID in (" & strWhere & ")"
CurrentProject.Connection.Execute strSQL
strWhere = ""
End If
Loop
End If
This way works much faster than one-by one looping thru the recordset. The speed is similar to using "normal" WHERE clause with all conditions.
Chunk size=100 was most optimal for performance in my case, you can try different chunk sizes and find most optimal size for your table.
来源:https://stackoverflow.com/questions/42502250/moving-records-from-one-table-to-another