J'ai une table JET
avec un numéro automatique comme clé primaire, et je voudrais savoir comment récupérer ce numéro après avoir inséré une ligne. J'ai pensé à utiliser MAX()
pour récupérer la ligne avec la valeur la plus élevée, mais je ne sais pas à quel point ce serait fiable. Quelques exemples de code:
Dim query As String
Dim newRow As Integer
query = "INSERT INTO InvoiceNumbers (date) VALUES (" & NOW() & ");"
newRow = CurrentDb.Execute(query)
Maintenant, je sais que cela ne fonctionnerait pas, car Execute()
ne retournera pas la valeur de la clé primaire, mais c'est essentiellement le type de code que je recherche. Je devrai utiliser la clé primaire de la nouvelle ligne pour mettre à jour un certain nombre de lignes dans une autre table.
Quelle serait la manière la plus simple/la plus lisible de procéder?
Si DAO
utilisez
RS.Move 0, RS.LastModified
lngID = RS!AutoNumberFieldName
Si ADO
utilisez
cn.Execute "INSERT INTO TheTable.....", , adCmdText + adExecuteNoRecords
Set rs = cn.Execute("SELECT @@Identity", , adCmdText)
Debug.Print rs.Fields(0).Value
cn
étant une connexion valide ADO, @@Identity
renverra le dernier Identity
(numéro automatique) inséré sur cette connexion.
Notez que @@Identity
peut être gênant car la dernière valeur générée peut ne pas être celle qui vous intéresse. Pour le moteur de base de données Access, considérez un VIEW
qui joint deux tables, qui ont toutes les deux IDENTITY
propriété, et vous INSERT INTO
le VIEW
. Pour SQL Server, déterminez s'il existe des déclencheurs qui à leur tour insèrent des enregistrements dans une autre table qui possède également la propriété IDENTITY
.
BTW DMax
ne fonctionnerait pas comme si quelqu'un d'autre insérait un enregistrement juste après que vous en ayez inséré un mais avant que votre fonction Dmax
termine son exécution, alors vous obtiendriez son enregistrement.
Dans votre exemple, parce que vous utilisez CurrentDB pour exécuter votre INSERT, vous avez rendu la tâche plus difficile. Au lieu de cela, cela fonctionnera:
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
J'avais l'habitude de faire des INSERT en ouvrant un jeu d'enregistrements AddOnly
et en récupérant l'ID à partir de là, mais c'est ici beaucoup plus efficace. Et notez qu'il ne nécessite pas ADO
.
Ceci est une adaptation de mon code pour vous. Je me suis inspiré de developpez.com (Cherchez dans la page: " Pour insérer des données, vaut-il mieux passer par un RecordSet ou par une requête de type INSÉRER? "). Ils expliquent (avec un peu de français). Cette façon est beaucoup plus rapide que celle supérieure. Dans l'exemple, cette méthode était 37 fois plus rapide. Essayez-le.
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
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
Les deux exemples ci-dessus ne fonctionnaient pas pour moi. L'ouverture d'un jeu d'enregistrements sur la table et l'ajout d'un enregistrement fonctionnent pour ajouter l'enregistrement, sauf:
myLong = CLng(rs!AutoNumberField)
renvoie Null s'il est placé entre rs.AddNew et rs.Update. Si mis après rs.Update, il retourne quelque chose, mais c'est toujours faux et toujours la même valeur incorrecte. L'examen du tableau directement après l'ajout du nouvel enregistrement montre une valeur de champ de numérotation automatique différente de celle renvoyée par l'instruction ci-dessus.
myLong = DLookup("AutoNumberField","TableName","SomeCriteria")
fonctionnera correctement, tant qu'il est effectué après rs.Update, et il existe d'autres champs qui peuvent identifier l'enregistrement de manière unique.