2009-10-27 75 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