Get ID of Last Inserted Record - Access DAO, ODBC, SQL Server 2008 Identity Field

三世轮回 提交于 2021-02-07 19:46:00

问题


It's a very common question but I'm having trouble getting the ID of the last inserted record. I'm using DAO with ODBC linked tables to duplicate a record and it's child records. My tables are in SQL Server 2008 and have Identity fields for ID fields.

Here's what I've tried so far. My first bit of code here results in error 3167, Record is Deleted. If I do a debug.Print the recordset actually contains 3 records.

Dim r as DAO.Recordset, db as DAO.Database
Set db = CurrentDb
Set r = db.OpenRecordset("SELECT TOP 2 * FROM item ORDER BY DateTimeModified DESC", dbOpenDynaset, dbSeeChanges)
r.AddNew
'Set field values here
r.Update 'Completes without error
r.Bookmark = r.LastModified
Debug.Print r("ItemID") 'Error 3167, Record is deleted

Here's the next thing I tried:

Debug.Print db.OpenRecordset("SELECT @@identity FROM item")(0)

This last one completes without any problem but the value returned is incorrect. Where the actual new ItemID is 321 this returns the value 614. The value it is returning does appear to be incremental (it changes as I keep testing this) but it does not appear to relate at all to my table. There is no field with the value 614. I've double checked to make sure I'm looking up the correct table.

I know I could use something like DLookup or DMax but I don't think that would be considered bullet proof in a multi-user environment.

I suppose I could use a Stored Procedure with ADO to get around this problem. I'm wondering if that is my only option?

Edit1:
I'm now using the following code and it is doing what I need/want it to. I suspect this is basically the same as using DMax.

Dim r as DAO.Recordset, db as DAO.Database
Set db = CurrentDb
Set r = db.OpenRecordset("SELECT TOP 1 * FROM item ORDER BY ItemID DESC", dbOpenDynaset, dbSeeChanges)
r.AddNew
'Set field values here
r.Update
r.Requery
r.MoveFirst
Debug.Print r("ItemID")

回答1:


As far as I'm aware @@IDENTITY doesn't work for cursor-based inserts. DAO and ADO both use cursors behind the scenes.

After you .Update the record you should be able to get the identity value back simply by reading the value.

The following works fine for me via an ADO Recordset opened with Keyset semantics:

r.Update
Debug.Print r("ItemID")

The following works fine for me via a DAO Recordset opened with Dynaset semantics:

r.Update
r.Bookmark = r.LastModified
Debug.Print r("ItemID")

You should avoid .Requery and .MoveFirst, you're introducing concurrency problems. Consider:

Dim r as DAO.Recordset, db as DAO.Database
Set db = CurrentDb
Set r = db.OpenRecordset("SELECT TOP 1 * FROM item ORDER BY ItemID DESC", dbOpenDynaset, dbSeeChanges)
r.AddNew
''// Set field values here
r.Update
''// At this point another user adds a new record
r.Requery
r.MoveFirst ''// ORDER BY ItemID DESC means that you're going to see the new user's row
Debug.Print r("ItemID")



回答2:


The following works as expected (using Office 2013 and SQL Server 2014)

Set rsProjects = db.OpenRecordset("JobProjects", dbOpenDynaset, dbSeeChanges Or dbAppendOnly)
rsProjects.AddNew
rsProjects.Name = 'xyz'
rsProjects.Update
rsProjects.Bookmark = rsProjects.LastModified
lNewProjectID = rsProjects!ProjectID.Value

Key point: instead of using 'SELECT TOP 2' or 'SELECT TOP 1', etc. I used 'dbSeeChanges Or dbAppendOnly'. I verified in sql profiler that opening the recordset does not generate any queries to SQL Server.

When you issue the update, access generates an insert statement followed immediately by a SELECT @@IDENTITY to get the id of the new record.

Edited: add missing .AddNew, Remove duplicate .Update.




回答3:


it dosnt work with sql server backend(in multi user app ). for access table it work for sql use stored procedure.use this way

CREATE PROCEDURE dbo.AddAsset

  @Name VARCHAR(500),
  @URL  VARCHAR(2000),
  @new_identity INT = NULL OUTPUT
AS
BEGIN
    SET NOCOUNT ON;

INSERT dbo.Assets(Name, URL) SELECT @Name, @URL;
SET @new_identity = SCOPE_IDENTITY();

END 
GO

then use this sp in front end




回答4:


Simply get the value of the key field before you execute the Update statement. As pointed out in the comment below, this process will not work if you are using a different backend than Microsoft Access. But I leave this response here in case that is your use case and you are just searching for an answer to the general question of how you get the ID of the last inserted record.

For your example, you can do this with Microsoft Access:

Dim r as DAO.Recordset, db as DAO.Database
Dim lKey As Long
Set db = CurrentDb
Set r = db.OpenRecordset("SELECT TOP 2 * FROM item ORDER BY DateTimeModified DESC", dbOpenDynaset, dbSeeChanges)
r.AddNew
    'Set field values here
    'Retrieve the key value before executing the Update
    lKey = r!ItemID
r.Update
Debug.Print lKey


来源:https://stackoverflow.com/questions/10905596/get-id-of-last-inserted-record-access-dao-odbc-sql-server-2008-identity-fiel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!