Inspired by https://www.access-programmers.co.u...oid-the-domain-functions-in-ms-access.330010/ I am trying to compare insert variants in VBA in this thread.
First of all: I only discuss the variants that can be used with Jet/ACE (e.g. executing procedures in an active DBMS is not included).
In principle, there are 2 basic variants:
1. Execute an SQL insert statement (SQL directly, stored query with parameters, ... + get autonum/identity from select @@identity, max(id), ....)
2. Insert via a recordset (DAO or ADDOB)
Principle approach for 1:
Problem with @@Identity:
If an insert trigger is running and an autonum is assigned in another table in this trigger, this is output.
Problem with Max(AutoNumFieldName)
In a multi-user environment, it is essential to ensure that the insert statement and the query of Max(AutoNumFieldName) run within a transaction so that no values are output by another user. Of course, AutoNum must also be set to ascending. (But that will be true most of the time.)
Principle approach for 2:
In my opinion, this is the most stable option.
The disadvantage of this variant is that it is difficult to write in a general reusable function, as field names and their values must be transferred.
With the SQL variant, it is basically sufficient to pass the SQL statement (and with Max(...) the name of the data field to be queried)
Example file see attachment.
Note: The procedures contained in the example are intentionally not designed as reusable (for different data sources) procedures so that only the essential code is easier to read because no complex interfaces are required.
However, we can discuss the design of the reusable procedures and show possibilities.
First of all: I only discuss the variants that can be used with Jet/ACE (e.g. executing procedures in an active DBMS is not included).
In principle, there are 2 basic variants:
1. Execute an SQL insert statement (SQL directly, stored query with parameters, ... + get autonum/identity from select @@identity, max(id), ....)
2. Insert via a recordset (DAO or ADDOB)
Principle approach for 1:
Code:
InsertSql = "insert into tabTest(N, T, D) ...."
db.execute InsertSql
' a) @@Identity
With db.OpenRecordset("select @@Identity", dbOpenForwardOnly, dbReadOnly)
NewId = .Fields(0)
.Close
End With
' b) Max(AutoNumFieldName) ... (if ascending)
With db.OpenRecordset("select Max(AutoNumFieldName) from ...", dbOpenForwardOnly, dbReadOnly)
NewId = .Fields(0)
.Close
End With
Problem with @@Identity:
If an insert trigger is running and an autonum is assigned in another table in this trigger, this is output.
Problem with Max(AutoNumFieldName)
In a multi-user environment, it is essential to ensure that the insert statement and the query of Max(AutoNumFieldName) run within a transaction so that no values are output by another user. Of course, AutoNum must also be set to ascending. (But that will be true most of the time.)
Principle approach for 2:
Code:
With db.OpenRecordset(Source, dbOpenDynaset, dbAppendOnly)
.AddNew
.Fields(...).Value = ...
...
.Update
.Bookmark = .LastModified
NewId = .Fields(AutoNumFieldName).Value
.Close
End With
The disadvantage of this variant is that it is difficult to write in a general reusable function, as field names and their values must be transferred.
With the SQL variant, it is basically sufficient to pass the SQL statement (and with Max(...) the name of the data field to be queried)
Example file see attachment.
Note: The procedures contained in the example are intentionally not designed as reusable (for different data sources) procedures so that only the essential code is easier to read because no complex interfaces are required.
However, we can discuss the design of the reusable procedures and show possibilities.