2009-10-27 8 views
31

Ich habe eine JET-Tabelle mit einer Auto-Nummer als Primärschlüssel, und ich würde gerne wissen, wie ich diese Nummer nach Einfügen eine Zeile abrufen kann. Ich habe daran gedacht, MAX() zu verwenden, um die Zeile mit dem höchsten Wert abzurufen, bin mir aber nicht sicher, wie zuverlässig das sein würde. Einiger Beispielcode:Autowert der zuletzt eingefügte Zeile - MS Access/VBA

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

Jetzt weiß ich, dass dies nicht funktionieren würde, da Execute() nicht den Wert des Primärschlüssels zurück, aber das ist im Grunde die Art von Code die ich suche. Ich muss den Primärschlüssel der neuen Zeile verwenden, um eine Anzahl von Zeilen in einer anderen Tabelle zu aktualisieren.

Was die einfachste/lesbarsten Weise sein würde, dies zu tun?

Antwort

32

Wenn DAO

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

verwenden Wenn ADO cn

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

verwenden eine gültige ADO-Verbindung ist, wird die letzte @@Identity Identity (Autowert) auf dieser Verbindung eingesetzt zurückzukehren.

Beachten Sie, dass @@Identity lästig sein könnte, da der letzte erzeugte Wert nicht diejenige, die Sie interessieren werden können. Für die Access-Datenbank-Engine, eine VIEW betrachten, die zwei Tabellen verknüpft, die beide über die IDENTITY Eigenschaft, und Sie INSERT INTO die VIEW. Denken Sie bei SQL Server darüber nach, ob es Trigger gibt, die wiederum Datensätze in eine andere Tabelle einfügen, die auch die Eigenschaft IDENTITY aufweist.

BTW DMax würde nicht funktionieren, als ob jemand anderes einen Datensatz einfügt, direkt nachdem Sie einen Datensatz eingefügt haben, aber bevor Ihre Dmax-Funktion beendet wird, erhalten Sie ihre Aufzeichnung.

+14

DAO können Sie SELECT @@ IDENTITY auch - Sie müssen nicht ADO benötigen. Ich mache das die ganze Zeit: lngID = db.OpenRecordset ("SELECT @@ IDENTITY") (0), wobei "db" dieselbe Datenbankvariable ist, die zum Ausführen der Einfügung verwendet wurde. Ich öffne keine Recordsets mehr und füge das hinzu. –

41

In Ihrem Beispiel, weil Sie CurrentDB verwenden Ihre INSERT ausführen Sie es für sich selbst schwerer gemacht haben. Stattdessen wird diese Arbeit:

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 

Früher habe ich zu tun, fügt durch einen AddOnly-Cord öffnen und die ID von dort Abholung, aber das ist viel effizienter. Und beachten Sie, Tony, dass es keine ADO erfordert.

+2

und es funktioniert, auch wenn das Recordset eine SQL Server-verknüpfte Tabelle ist! Wunderbar! –

+0

Sie können auch dbFailOnError als Option zum Ausführen hinzufügen. Andernfalls wird Access nichts sagen, wenn es fehlschlägt. ----- db.Abfrage ausführen, dbFailOnError – JustJohn

+0

@iDevlop SQL Server unterstützt [die SELECT @ IDENTITY-Syntax] (https://msdn.microsoft.com/en-us/library/ms187342.aspx). Es wäre interessant zu sehen, was in anderen verknüpften Tabellentypen wie Excel oder anderen RDBMS wie Oracle oder MySQL passiert. –

3

Dies ist eine Adaption von meinem Code für Sie. Ich wurde von developpez.com (Schauen Sie auf der Seite für: "Gießen insérer des données, vaut-il mieux Passant par un RecordSet ou par une requête de type INSERT?") Inspiriert. Sie erklären (mit ein wenig Französisch). Dieser Weg ist viel schneller als der obere. Im Beispiel war dieser Weg 37 mal schneller. Versuch es.

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

Könnten Sie bitte identifizieren, welches spezielle Beispiel es "37 Mal schneller" ist als? –

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

Ich sehe nicht, wie dies die ursprüngliche Frage beantwortet. Bitte fügen Sie Kontext hinzu, um zu sehen, wie das passt? – GPI

+1

Diese Antwort ist unklar. Bitte fügen Sie Erklärungen hinzu. Nicht alle von uns wissen ** alles über VBA. – MJH

Verwandte Themen