2009-10-27 78 views
31

我有一个自动编号作为主键的JET表,我想知道如何在插入一行后检索此编号。我曾想过使用MAX()来检索具有最高值的行,但我不确定这将是多么可靠。一些示例代码:最后插入行的自动编号值 - MS Access/VBA

Dim query As String 
Dim newRow As Integer 
query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");" 
newRow = CurrentDb.Execute(query) 

现在我知道,这是行不通的,因为Execute()将不会返回主键的值,但是这基本上是我要找的那种代码。我将需要使用新行的主键来更新另一个表中的多个行。

这样做最简单/最可读的方法是什么?

回答

32

如果DAO使用

RS.Move 0, RS.LastModified 
lngID = RS!AutoNumberFieldName 

如果ADO使用

cn.Execute "INSERT INTO TheTable.....", , adCmdText + adExecuteNoRecords 
Set rs = cn.Execute("SELECT @@Identity", , adCmdText) 
Debug.Print rs.Fields(0).Value 

CN是一个有效的ADO连接,@@Identity将返回插入此连接上最后 Identity(自动编号)。

注意@@Identity可能是麻烦,因为最后生成的值可能不是一个你感兴趣的,对于Jet数据库引擎,考虑VIEW联接两个表,这两者有IDENTITY属性,你INSERT INTOVIEW。对于SQL Server,请考虑是否有触发器将记录插入另一个也具有IDENTITY属性的表中。

顺便说一句,DMax不会工作,就好像其他人在插入记录之后插入记录一样,但是在Dmax函数完成执行之前,您将获得他们的记录。

+14

DAO可以做SELECT @@ IDENTITY,太 - 你不需要ADO。我一直这样做:lngID = db.OpenRecordset(“SELECT @@ IDENTITY”)(0),其中“db”是用于执行插入的数据库变量。我不再打开记录集并为此添加。 – 2009-10-27 20:03:44

41

在你的例子中,因为你使用CurrentDB来执行你的INSERT,你已经让自己变得更加困难。取而代之的是,这将工作:

Dim query As String 
    Dim newRow As Long ' note change of data type 
    Dim db As DAO.Database 

    query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");" 
    Set db = CurrentDB 
    db.Execute(query) 
    newRow = db.OpenRecordset("SELECT @@IDENTITY")(0) 
    Set db = Nothing 

我用来做通过打开AddOnly记录,并从那里拿起ID增加,但是这是一个很大的效率。而且,请注意,托尼,它不需要ADO。

+2

即使记录集是SQL Server链接表,它也可以工作!太好了! – 2014-01-14 14:19:09

+0

您可能还会将dbFailOnError添加为执行的选项。 否则如果访问失败,Access不会说任何内容。 ----- db。执行查询,dbFailOnError – JustJohn 2015-06-19 21:55:33

+0

@iDevlop SQL Server支持[SELECT @@ IDENTITY'语法](https://msdn.microsoft.com/en-us/library/ms187342.aspx)。看看其他链接表类型(如Excel)或其他RDBMS(如Oracle或MySQL)会发生什么会很有趣。 – 2015-08-30 19:17:37

3

这是从我的代码适合你。我受到developpez.com的启发(请查看:“请注意,请注意不要使用RecordSet或INSERT?”)。他们解释(用一点法语)。这种方式比上一个速度快得多。在这个例子中,这种方式快了37倍。尝试一下。

Const tableName As String = "InvoiceNumbers" 
Const columnIdName As String = "??" 
Const columnDateName As String = "date" 

Dim rsTable As DAO.recordSet 
Dim recordId as long 

Set rsTable = CurrentDb.OpenRecordset(tableName) 
Call rsTable .AddNew 
recordId = CLng(rsTable (columnIdName)) ' Save your Id in a variable 
rsTable (columnDateName) = Now()  ' Store your data 
rsTable .Update 

recordSet.Close 

LeCygne

+3

您能否确定哪个特定示例比“快37倍”? – 2009-11-29 05:10:31

1
Private Function addInsert(Media As String, pagesOut As Integer) As Long 


    Set rst = db.OpenRecordset("tblenccomponent") 
    With rst 
     .AddNew 
     !LeafletCode = LeafletCode 
     !LeafletName = LeafletName 
     !UNCPath = "somePath\" + LeafletCode + ".xml" 
     !Media = Media 
     !CustomerID = cboCustomerID.Column(0) 
     !PagesIn = PagesIn 
     !pagesOut = pagesOut 
     addInsert = CLng(rst!enclosureID) 'ID is passed back to calling routine 
     .Update 
    End With 
    rst.Close 

End Function 
+1

我不明白这是如何回答原来的问题。请添加上下文以了解它如何适合? – GPI 2014-08-06 20:31:43

+1

这个答案不清楚。请添加解释。不是我们所有人都知道关于vba的一切**。 – MJH 2016-01-04 09:16:07