Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SELECT @@IDENTITY not scoped by DB object?

Tags:

jet

ms-access

I have the following code in MS Access:

Sub IdentityFail()
Dim db1 As DAO.Database, db2 As DAO.Database
Dim id1 As Long, id2 As Long

    CurrentDb.Execute "CREATE TABLE LocalDummy (Col1 AUTOINCREMENT, Col2 INT)", dbFailOnError
    Set db1 = CurrentDb
    Set db2 = CurrentDb
    db1.Execute "INSERT INTO LocalDummy(Col2) VALUES(Null)", dbFailOnError
    id1 = db1.OpenRecordset("SELECT @@IDENTITY")(0)
    db2.Execute "INSERT INTO LocalDummy(Col2) VALUES(Null)", dbFailOnError
    id2 = db2.OpenRecordset("SELECT @@IDENTITY")(0)

    Debug.Print id1, id2
    Debug.Print db1.OpenRecordset("SELECT @@IDENTITY")(0), _
                db2.OpenRecordset("SELECT @@IDENTITY")(0), _
                CurrentDb.OpenRecordset("SELECT @@IDENTITY")(0)
End Sub

I would expect this to output the following (ie, each distinct db object would have its own "most recent identity" value):

1     2
1     2    0

Instead I get (ie, it appears to be globally scoped):

1     2
2     2    2

I thought SELECT @@IDENTITY was the safe way to get the latest autonumber ID in Jet 4.0+. What am I doing wrong?

like image 988
mwolfe02 Avatar asked Jan 20 '23 19:01

mwolfe02


1 Answers

Turns out that SELECT @@IDENTITY is scoped by session. In ADO, this is handled via the connection. In DAO, we have to use Workspaces to isolate the scope. The following code works as expected:

Sub IdentitySucceed()
Dim ws1 As DAO.Workspace, ws2 As DAO.Workspace
Dim db1 As DAO.Database, db2 As DAO.Database
Dim id1 As Long, id2 As Long, DbPath As String

    CurrentDb.Execute "CREATE TABLE LocalDummy (Col1 AUTOINCREMENT, Col2 INT)", dbFailOnError
    'The workspace names need not be unique;'
    '  we'll use the objects themselves (ws1 and ws2) to keep them straight'
    Set ws1 = DAO.CreateWorkspace("TempWS", "Admin", "")
    Set ws2 = DAO.CreateWorkspace("TempWS", "Admin", "")
    DbPath = Application.CurrentProject.Path & "\" & _
             Application.CurrentProject.Name
    Set db1 = ws1.OpenDatabase(DbPath)
    Set db2 = ws2.OpenDatabase(DbPath)
    db1.Execute "INSERT INTO LocalDummy(Col2) VALUES(Null)", dbFailOnError
    id1 = db1.OpenRecordset("SELECT @@IDENTITY")(0)
    db2.Execute "INSERT INTO LocalDummy(Col2) VALUES(Null)", dbFailOnError
    id2 = db2.OpenRecordset("SELECT @@IDENTITY")(0)

    Debug.Print id1, id2
    Debug.Print db1.OpenRecordset("SELECT @@IDENTITY")(0), _
                db2.OpenRecordset("SELECT @@IDENTITY")(0), _
                CurrentDb.OpenRecordset("SELECT @@IDENTITY")(0)
End Sub

This outputs the following:

1    2
1    2    2

CurrentDb still won't return 0, but that's easy enough to code around.

like image 69
mwolfe02 Avatar answered Feb 16 '23 03:02

mwolfe02