3

这是一个非常常见的问题,但我无法获取最后插入的记录的 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)

最后一个完成没有任何问题,但返回的值不正确。如果实际的新 ItemID 为 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")
4

4 回答 4

6

据我所知@@IDENTITY,不适用于基于光标的插入。DAO 和 ADO 都在幕后使用游标。

在您.Update记录之后,您应该能够通过读取值来获取标识值。

通过使用键集语义打开的 ADO 记录集,以下内容对我来说很好:

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

以下通过使用动态集语义打开的 DAO 记录集对我来说很好:

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

您应该避免.Requeryand .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")
于 2012-06-06T00:18:19.373 回答
1

以下按预期工作(使用 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

关键点:我没有使用“SELECT TOP 2”或“SELECT TOP 1”等。我使用了“dbSeeChanges或 dbAppendOnly ”。我在 sql profiler 中验证了打开记录集不会生成对 SQL Server 的任何查询。

当您发出更新时,access 会生成一个插入语句,然后立即使用 SELECT @@IDENTITY 来获取新记录的 id。

已编辑:添加缺少的 .AddNew,删除重复的 .Update。

于 2016-11-02T17:03:34.947 回答
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

于 2015-03-29T18:11:44.637 回答
-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
于 2012-12-24T22:03:28.123 回答