Значение Autonumber последней вставленной строки - MS Access/VBA
У меня есть таблица JET с автоматическим номером в качестве первичного ключа, и я хотел бы знать, как я могу получить это число после вставки строки. Я думал о том, чтобы использовать MAX() для извлечения строки с наивысшим значением, но я не уверен, насколько это было бы достоверно. Пример кода:
Dim query As String
Dim newRow As Integer
query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");"
newRow = CurrentDb.Execute(query)
Теперь я знаю, что это не сработает, поскольку Execute()
не вернет значение первичного ключа, но это в основном тот тип кода, который я ищу. Мне нужно будет использовать первичный ключ новой строки для обновления ряда строк в другой таблице.
Каким будет самый простой/наиболее читаемый способ сделать это?
Ответы
Ответ 1
Если 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
.
BTW DMax не будет работать так, как если бы кто-то еще вставлял запись сразу после того, как вы вставили запись, но прежде чем ваша функция Dmax закончит excecuting, вы получите свою запись.
Ответ 2
В вашем примере, поскольку вы используете 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 и собирая идентификатор оттуда, но это намного эффективнее. И, обратите внимание, Тони, что он не требует ADO.
Ответ 3
Это адаптация моего кода для вас. Я был вдохновлен developpez.com (Смотрите на странице для: "Pour insérer des données, vaut-il mieux passer par un RecordSet ou par une requête типа 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
Ответ 4
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