Значение автонумерации последней вставленной строки - MS Access / VBA - PullRequest
35 голосов
/ 27 октября 2009

У меня есть таблица JET с автоматическим номером в качестве первичного ключа, и я хотел бы знать, как я могу получить этот номер после вставки строки. Я думал об использовании MAX() для получения строки с самым высоким значением, но я не уверен, насколько это будет надежно. Пример кода:

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

Теперь я знаю, что это не сработает, поскольку Execute() не будет возвращать значение первичного ключа, но в основном это тот код, который я ищу. Мне нужно будет использовать первичный ключ новой строки, чтобы обновить количество строк в другой таблице.

Какой самый простой / читаемый способ сделать это?

Ответы [ 5 ]

45 голосов
/ 27 октября 2009

В вашем примере, потому что вы используете 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

Раньше я делал INSERT, открывая набор записей AddOnly и выбирая оттуда идентификатор, но это гораздо эффективнее. И обратите внимание, что это не требует ADO.

37 голосов
/ 27 октября 2009

Если 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 (Autonumber) вставлен в это соединение.

Обратите внимание, что @@Identity может быть проблематично, потому что последнее сгенерированное значение может не совпадать с интересующим вас. Для ядра базы данных Access рассмотрим VIEW, который объединяет две таблицы, каждая из которых имеет IDENTITY собственности, а вы INSERT INTO VIEW. Для SQL Server рассмотрите, есть ли триггеры, которые в свою очередь вставляют записи в другую таблицу, которая также имеет свойство IDENTITY.

КСТАТИ DMax не будет работать так, как если бы кто-то вставил запись сразу после того, как вы ее вставили, но до того, как ваша функция Dmax завершит выполнение, тогда вы получите их запись.

5 голосов
/ 27 ноября 2009

Это адаптация из моего кода для вас. Я был вдохновлен с 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 голосов
/ 07 августа 2014
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
0 голосов
/ 29 мая 2019

Оба приведенных выше примера не сработали для меня. Открытие набора записей в таблице и добавление записи действительно помогает добавить запись, кроме:

myLong = CLng(rs!AutoNumberField)

возвращает Null, если поместить между rs.AddNew и rs.Update. Если поставить после rs.Update, он возвращает что-то, но это всегда неправильно и всегда одно и то же неверное значение. Если вы посмотрите на таблицу непосредственно после добавления новой записи, вы увидите значение поля автонумерации, отличное от того, которое было возвращено вышеприведенным оператором.

myLong = DLookup("AutoNumberField","TableName","SomeCriteria")

будет работать правильно, если это сделано после rs.Update, и есть любые другие поля, которые могут однозначно идентифицировать запись.

...