Get record written data

I currently use the following VBA code to get the MAX record just after commit:
<BEGIN VBA>    Dim strSQLLot As String
    Dim strSQLFailure As String
    Dim intFailed As Integer
    Dim intCounter As Integer
    Dim dbConn As ADODB.Connection
    Dim recSet As ADODB.Recordset
    Dim intNextFailureId As Integer
    Dim intArray() As Integer
    Dim dbs As DAO.Database
    Dim rsSQL As DAO.Recordset
    Dim intMaxLotId As Integer
    Dim intNewLotID As Integer
'Open the database
        Set dbConn = CurrentProject.Connection
       
        'Write the form's data to the SQL table tblInitialData
        DoCmd.RunCommand acCmdSaveRecord
                               
        'determine MAX Lot ID number
        DoCmd.RunMacro "mcrRunqryMaketblMaxLotID"
        intMaxLotId = DLookup("MaxOfTestLotID", "tblMaxLotID")
       
        'Prompt user with MAX Lot ID Number.
        MsgBox "Lot number " & intMaxLotId & " has been created.", , "ATE DATABASE"
                       
        DoCmd.Close
                       
        'open switchboard and close initial form
        DoCmd.OpenForm "Switchboard"
<END VBA>

I previously tried to get a SELECT statement to run but had no luck.  I would like to use either SCOPE_IDENTITY() or @@IDENTITY but cannot determine the correct VBA to make that run.  Indeed, will it even run in scope based on using the DoCmd.RunCommand acCmdSaveRecord statement instead of an INSERT INTO statement?  I have tried DoCmd.OpenQuery, CurrentDb.Execute, and others that apparently do not allow SELECT statements.

TIA,
Tim
gibneytAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Éric MoreauSenior .Net ConsultantCommented:
check "Retrieving Microsoft Access Autonumber Values" from https://msdn.microsoft.com/en-us/library/ks9f57t0.aspx?f=255&MSPPError=-2147217396
0
Nick67Commented:
What you are attempting is a little trickier than you might think.
Dlookup() is a performance pig.
None of the domain lookup functions should EVER be used.
This will find the 'largest' value depending on datatype and sort order
Dim rs As dao.Recordset
Set rs = db.OpenRecordset("SELECT TOP 1 TheFieldOfInterest FROM TheTableOfInterest  ORDER BY  TheFieldOfInterest DESC;", dbOpenDynaset, dbSeeChanges)

TheMaxValue = rs!TheFieldOfInterest

No matter how you do it though, you have to be aware you are in a multi-user setup.
No matter how fast you think you may be, what gets retrieved may be the value from the record just committed -- or from someone else's new addition.

@@IDENTITY is at the SQL Server end of things.
You can get that back to Access -- but not if you are letting the users create the record via a bound form as you appear to be doing (DoCmd.RunCommand acCmdSaveRecord)

If you create the record with DAO, pulling back the identity is fairly simple.

   With rs
        .AddNew
        !MyField = MyValue
        .Update
        .Bookmark = .LastModified
        lngJobID = ![JobID]
    End With

Where my identity field is JobID and a Long (SQL Server bit) value.

But note that this value has NO guarantee of actually being the last record in play.
If you use the value to build a value that's unique (like work order or invoice numbers)  you need to build a check in to ensure that an attempted value is ACTUALLY valid when you go to use it.
0
Valliappan ANSenior Tech ConsultantCommented:
I would suggest that use MS Access only for single user run and SQL Server for multiple user run, and then using MAX(JobID) as already discuss here, would work in Access, and in SQL Server, you can use SCOPE_IDENTITY() to retrieve the last value.

Hope that helps.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

PatHartmanCommented:
Since you are running the code in a bound form, you don't need to use either the DLooku() or @@Identity query.  Simply reference the identity column in the form's RecordSource.

intMaxLotId = Me.LotID

If you run an append query, then you can't access the identity column and that is when you would need to use the @@Identity query to retrieve it.  So after running the append query or using DAO or ADO to inset a record use:
            Set rsScope = db.OpenRecordset("SELECT @@IDENTITY as NewID")
                       NewProvProcID = rsScope!NewID

Open in new window


As long as you don't have any triggers that will cause inserts into other tables, this will give you the last identity column inserted in this thread.

@Valliappan AN - Access (more specifically Jet and ACE) is not a single user application.  It is multi-user out of the box.

@Nick - when the tables are bound to SQL server, you cannot reference the Identity column this way.  It works with Jet/ACE due to the close connection Access has with them but Access' connection with SQL Server et al is asynchronous and so the insert has to be sent to the server (ie saved) before you can retrieve the new identity value.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Nick67Commented:
@PatHartman
I am confused
"you cannot reference the Identity column this way"
Perhaps I did not phrase things as clearly as I would have liked.
Dim rs As dao.Recordset
 Set rs = db.OpenRecordset("SELECT TOP 1 TheFieldOfInterest FROM TheTableOfInterest  ORDER BY  TheFieldOfInterest DESC;", dbOpenDynaset, dbSeeChanges)
 TheMaxValue = rs!TheFieldOfInterest

Open in new window


This will get the largest committed value of [TheTableOfInterest].[TheFieldOfInterest]
When you have an Access backend, Access will put a hold on an autonumber the minute you begin to make a new record dirty, and you can retrieve that.  SQL Server does not behave that way.  The identity value isn't set until the record is committed.
This code creates a new record, commits it and retrieves the identity value of that.
    With rs
         .AddNew
         !MyField = MyValue
         .Update
         .Bookmark = .LastModified
         lngJobID = ![JobID]
     End With

Open in new window


and works swimmingly with a SQL Server backend.
But absolutely, if a SQL Server backend is in play, you cannot retrieve the identity value of a 'dirty and new' record of a form -- which is something that is possible with an Access backend.  Only committing to save the record causes that identity value to be set in a SQL Server backend.

Is that what you meant?
0
PatHartmanCommented:
Sorry, I read the code wrong.  It looked like the reference was inside the .addnew rather than outside it.
0
gibneytAuthor Commented:
@PatHartman,

Nice!  Accessing the form's RecordSource in this instance does appear to be the shortest and sweetest means to an end.

Many thanks.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
VBA

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.