问题
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