Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
Home
Discussion GroupsVB SyntaxEnterprise DevelopmentDatabase AccessControlsCOMWin APICrystal ReportDeploymentGeneralGeneral 2
Related Topics
VB.NET / ASP.NETMS SQL ServerMS AccessOther Database ProductsMore Topics ...

VB Forum / Database Access / February 2008



Tip: Looking for answers? Try searching our database.

Compare two Recordsets

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
mse - 22 Feb 2008 15:04 GMT
I have an Microsoft Access Subform, where I delete some Records at once.
To enumerate the deleted records, I take two RecordSetClone of the form.
The first before deleting. (Set rstBefore = Me.RecordSetClone)
The second after deleting. (Set rstAfter = Me.RecordSetClone)
Now I want to compare the Recordsets.
Best would be to take an Inconsistence SQL-Query like this:

Set rstDifference = "SELECT rstBefore.Productname FROM rstBefore LEFT JOIN
rstAfter ON rstBefore.Productname = rstAfter.Productname WHERE
rstAfter.ProductName Is Null"

Is it possible to take Recordsets in SQL-Queries, instead of real tables?
If yes, how Do I define (Set) the rstDifference?

Manfred
Schmidt - 22 Feb 2008 15:38 GMT
> Is it possible to take Recordsets in SQL-Queries,
> instead of real tables?
No, you would have to loop yourself.

> If yes, how Do I define (Set) the rstDifference?
But if you want a difference between a "fresh" Rs-State
after coming from the DB and the Recordset-State after
some (GUI-forced) Inserts, Deletes or Updates, you can
achieve that (without using Clone or anything) using
the Filter-Property of the Rs itself (of course with
the right Params as e.g.: adFilterPendingRecords or
adFilterAffectedRecords).

Olaf
Manfred Senn - 23 Feb 2008 08:36 GMT
Thanks for the infos
I have done following but without success:
1. Runned Sub Test.
2. Deleted some records in Tabelle1.
3. Runned Test1.
Now, the deleted records should be shown (Line17).
But it doesn't. Why?

In Access 2003:

1   Option Compare Database
2
3   Dim rs As New ADODB.Recordset
4   Dim con As ADODB.Connection
5
6   Sub Test()
7      Set con = CurrentProject.Connection
8       rs.CursorLocation = adUseClient
9       rs.LockType = adLockBatchOptimistic
10     rs.Open "Select * From Tabelle1", con, adOpenKeyset
11  End Sub
12
13  Sub Test1()
14      rs.UpdateBatch
15      rs.Filter = adFilterAffectedRecords '
16      Do Until rs.EOF
17          Debug.Print rs!ID
18          rs.MoveNext
19      Loop
20      rs.Close
21  End Sub

>> Is it possible to take Recordsets in SQL-Queries,
>> instead of real tables?
[quoted text clipped - 10 lines]
>
> Olaf
Schmidt - 23 Feb 2008 14:34 GMT
> Thanks for the infos
> I have done following but without success:
[quoted text clipped - 5 lines]
> ...
> 10     rs.Open "Select * From Tabelle1", con, adOpenKeyset

You used the "wrong" Open-Parameters for this kind of task.

Look at this example:

'***Into a Form (using a copy of NWind, at: c:\NWind2.mdb)
Option Explicit

Private Cnn As Connection, Rs As Recordset

Private Sub Form_Load()
 Set Cnn = New Connection
 Cnn.CursorLocation = adUseClient
 Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\NWind2.mdb"

 Set Rs = New Recordset
 Rs.Open "Select * from Products",Cnn,adOpenStatic,adLockBatchOptimistic
 Debug.Print vbCrLf; "RecordCount after Select: "; Rs.RecordCount

 'here a simple Update of an existing Record (the first one)
 Rs!ProductName.Value = Rs!ProductName.Value & "X"

 'now we delete a record (the last one)
 Rs.MoveLast
 Rs.Delete

 'and finally an insert (Rs!ProductID is AutoInc, and left at Null here)
 Rs.AddNew
 Rs!ProductName.Value = "SomeNewRecord"

 Rs.Filter = adFilterPendingRecords
 Debug.Print vbCrLf; "Pending Records: "; Rs.RecordCount
 Do Until Rs.EOF
   Select Case Rs.Status
     Case adRecModified: Debug.Print "Update", Rs.Bookmark
     Case adRecNew: Debug.Print "Insert", Rs.Bookmark
     Case adRecDeleted: Debug.Print "Delete", Rs!ProductID.OriginalValue
   End Select
   Rs.MoveNext
 Loop

 On Error Resume Next
 Rs.UpdateBatch

 If Err Then 'Batch-update failed
   Rs.Filter = adFilterConflictingRecords
   'do your analysis here

 Else 'success
   Rs.Filter = adFilterAffectedRecords
   Debug.Print vbCrLf; "Affected Records: "; Rs.RecordCount

   'in case of success, the Deletes are included inside the filtered
   'RecordCount above, but inside the Loop you don't get them anymore
   Do Until Rs.EOF
     'here you can compare with the bookmarks above,
     'this way you should be able to verify, which records
     'were Inserts - and which Records were Updates (and as said,
     'Deletes are ot enumerated here anymore)
     Debug.Print Rs.Bookmark
     Rs.MoveNext
   Loop
 End If

 Rs.Filter = adFilterNone

 Rs.Close
 Cnn.Close
End Sub

Olaf
Manfred Senn - 24 Feb 2008 17:22 GMT
But this does not work when i delete a record manually, only when deleting
in code.

>> Thanks for the infos
>> I have done following but without success:
[quoted text clipped - 76 lines]
>
> Olaf
Schmidt - 24 Feb 2008 18:23 GMT
> But this does not work when i delete a record
> manually, only when deleting  in code.

Hmm, you are working inside Access - with the builtin
Controls - maybe there's something going on under the
hood you have no control over - in VB you can usually
manage these things on your own.

Maybe it helps, if you try to work with the ADO-
Recordsets in disconnected Mode:
Set Rs.ActiveConnection = Nothing
before you bind those Recordsets to the Access-
(Grid-)-Controls.

Olaf
Mark J. McGinty - 24 Feb 2008 22:23 GMT
Any changes to data in *any* clone of a given recordset, are instantly
visible in *all* clones, as well as the original recordset.  Each clone has
it's own filter, sort and current record pointer, but they all reference the
same data.

If you want to make a copy, as opposed to a clone, create an XML object,
persist the original recordset to it, and open a new recordset using the XML
as the source:

  Dim xml As MSXML2.DOMDocument
  Set xml = New MSXML2.DOMDocument
  rs.Save xml, adPersistXML
  rsCopy.Open xml

An alternative would be to use a batch cursor-based recordset, and read the
changes directly from XML.  A batch cursor recordset is just a static
recordset (rs.CursorLocation = adUseClient, rs.CursorType = adOpenStatic)
with LockType specified as adLockBatchOptimistic.

Given that the recordset has been persisted as above, the following returns
a node list, one node for each deleted record:

  Set DeleteNodes = xml.selectNodes("xml/rs:data/rs:delete/z:row")

In each node, attributes correspond to fields in the recordset, so you can
get the name and value of the first field in the first deleted row like so:

  DeleteNodes(0).attributes(0).name
  DeleteNodes(0).attributes(0).value

But better to get the attribute by name, because no assumptions should be
made about ordinal positions of the attributes:

  DeleteNodes(0).getAttribute("field1")

In fact, you could even easily undelete a row, simply by moving the node up
one row, making it a child of rs:data instead of rs:data/rs:deleted.

This technique may or may not fit your application, but it's likely worth
consideration.

-Mark

> But this does not work when i delete a record manually, only when deleting
> in code.
[quoted text clipped - 79 lines]
>>
>> Olaf
Manfred Senn - 27 Feb 2008 17:58 GMT
Thank you Olaf and Mark for your suggestions.
I solved the problem in another manner,
but I will keep your help in mind for any later programming ...
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2009 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.