这是一个非常常见的问题,但我无法获取最后插入记录的ID。我正在使用带有ODBC链接表的DAO来复制记录及其子记录。我的表位于SQL Server 2008中,并且具有ID字段的标识字段。
这是我到目前为止所尝试的内容。我的第一段代码导致错误3167,记录被删除。如果我执行debug.Print,记录集实际上包含3条记录。
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
这是我尝试的下一件事:
Debug.Print db.OpenRecordset("SELECT @@identity FROM item")(0)
最后一个完成没有任何问题,但返回的值不正确。当实际的新项目ID是321这个返回值614它返回确实出现了增量(它改变了,因为我一直在测试这个),但它不会出现在所有我的表,涉及的价值。没有值为614的字段。我已经仔细检查以确保我正在查找正确的表格。
我知道我可以使用像DLookup或DMax这样的东西,但我认为在多用户环境中不会被视为防弹。
我想我可以使用ADO存储过程来解决这个问题。我想知道这是否是我唯一的选择?
EDIT1:
我现在正在使用以下代码,它正在做我需要/想要的东西。我怀疑这与使用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")
答案 0 :(得分:4)
据我所知@@IDENTITY
对基于游标的插入不起作用。 DAO和ADO都在幕后使用游标。
在您.Update
记录之后,您应该只需阅读该值就能获得身份值。
以下通过使用Keyset语义打开的ADO Recordset可以正常工作:
r.Update
Debug.Print r("ItemID")
以下通过使用动态集语义打开的DAO Recordset可以正常工作:
r.Update
r.Bookmark = r.LastModified
Debug.Print r("ItemID")
您应该避免使用.Requery
和.MoveFirst
,这会引入并发问题。考虑:
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")
答案 1 :(得分:1)
以下按预期工作(使用Office 2013和SQL Server 2014)
Set rsProjects = db.OpenRecordset("JobProjects", dbOpenDynaset, dbSeeChanges Or dbAppendOnly)
rsProjects.Name = 'xyz'
rsProjects.Update
rsProjects.Update
rsProjects.Bookmark = rsProjects.LastModified
lNewProjectID = rsProjects!ProjectID.Value
关键点:而不是使用' SELECT TOP 2'或者'选择TOP 1'等我用过' dbSeeChanges 或dbAppendOnly '。我在sql profiler中验证打开记录集不会向SQL Server生成任何查询。
当您发出更新时,访问会生成一个insert语句,紧接着是SELECT @@ IDENTITY,以获取新记录的ID。
答案 2 :(得分:0)
它不适用于sql server后端(在多用户应用程序中 )。对于访问表它工作 对于sql使用存储过程。使用这种方式
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
然后在前端使用此sp
答案 3 :(得分:-1)
在执行Update
语句之前,只需获取关键字段的值即可。正如下面的评论所指出的,如果您使用的是与Microsoft Access不同的后端,则此过程将不起作用。但是我在这里留下这个回复以防你的用例,而你只是在寻找一个关于如何获得最后插入记录的ID的一般问题的答案。
对于您的示例,您可以使用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