非常常见的问题,但我无法获取上次插入记录的 ID。我正在使用 DAO 和 ODBC 链接表来复制记录及其子记录。我的表位于 SQL Server 2008 中,并且具有 ID 字段的标识字段。
这是我到目前为止尝试过的。我在这里的第一段代码导致错误 3167,记录被删除。如果我进行调试。打印记录集实际上包含 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)
最后一个完成没有任何问题,但返回的值不正确。如果实际的新 ItemID 为 321,则返回值 614。它返回的值似乎是增量的(随着我不断测试它而变化),但它似乎与我的表完全无关。没有值为 614 的字段。我已经仔细检查以确保我正在查找正确的表格。
我知道我可以使用DLookup或DMax之类的东西,但我认为这在多用户环境中不会被认为是防弹的。
我想我可以使用带有 ADO 的存储过程来解决这个问题。我想知道这是否是我唯一的选择?
编辑1:
我现在使用以下代码,它正在做我需要/想要它做的事情。我怀疑这与使用 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")
我所知@@IDENTITY
不适用于基于光标的插入。DAO 和 ADO 都在后台使用光标。
.Update
记录后,只需读取值即可取回标识值。
通过使用键集语义打开的 ADO 记录集,以下内容对我来说效果很好:
r.Update
Debug.Print r("ItemID")
通过用 Dynaset 语义打开的 DAO 记录集,以下内容对我来说效果很好:
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")
以下内容按预期工作(使用 Office 2013 和 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
关键点:而不是使用"选择前 2 名"或"选择前 1 名"等。我使用了'dbSeeChanges or dbAppendOnly'。我在 sql 探查器中验证了打开记录集不会生成对 SQL Server 的任何查询。
发出更新时,Access 会生成一个插入语句,后跟一个 SELECT @@IDENTITY,以获取新记录的 id。
已编辑:添加缺失的 .添加新,删除重复的。更新。
它不能与SQL Server Backend一起使用(在多用户应用程序中)).对于访问表,它工作对于 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
只需在执行 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