Transactions
- Last Updated: June 27, 2025
- 4 minute read
- OpenEdge
- Version 12.2
- Documentation
Transactions ensure that the data in your database maintains integrity. In this
topic, you learn about implicit and explicit transactions, and how the UNDO statement undoes a transaction.
Implicit transactions
During a transaction, information on all database activity occurring during that transaction is written to a before-image (or BI) file that is associated with the database. The BI file is located on the server with the other database files. The information written to the before-image file is coordinated with the timing of the data written to the actual database files. That way, if an error occurs during the transaction, the AVM automatically uses the before-image file to restore the database to the condition it was in before the transaction started.
FORblocks that directly update the databaseREPEATblocks that directly update the database- Procedure blocks that directly update the database
DOblocks with theON ERRORphrase that contain statements that update the database
The following example code starts a transaction for each iteration, resulting in the updates for each customer record as a separate transaction.
|
If your application has multiple nested blocks, each of which would be a transaction block if it stood on its own, then the outermost block is the transaction and all nested transaction blocks within it become subtransactions. All database activity occurring during a subtransaction is written to a local-before-image (or LBI) file.
- A procedure block that is run from a transaction block in another procedure
- Each iteration of a
FOR EACHblock nested within a transaction block - Each iteration of a
REPEATblock nested within a transaction block - Each iteration of a
DO TRANSACTIONorDO ON ERRORinside a transaction block
If an application error occurs during a subtransaction, all the work
done since the beginning of the subtransaction is undone. You can nest
subtransactions within other subtransactions. You can use the UNDO statement to programmatically undo a transaction
or subtransaction.
The following example code starts a transaction at the Customer level and Order changes are done in a subtransaction:
|
Explicit transactions
You can also start a transaction by adding the TRANSACTION keyword to a DO, FOR, or REPEAT block.
If your code starts a transaction in one procedure and then calls another procedure,
whether internal or external, the entire subprocedure is contained within the
transaction that was started before it was called. If a subprocedure starts a
transaction, then it must end within that subprocedure as well, because the
beginning and end of the transaction are always the beginning and end of a
particular block of code.
The following example code puts a transaction block around the whole update of both the Customer and any modified Orders:
|
UNDO statement
A transaction is automatically undone when an unhandled error occurs that kicks you out of the transaction block. Your application logic can also undo a transaction when you detect a violation within your business logic. The UNDO statement lets you control when to cancel the effects of a transaction on your own. It also lets you define just how much of your procedure logic to undo.
UNDO keyword as
its own statement. In this case, the AVM undoes the innermost containing block with
the error property, which can be:- A
FORblock - A
REPEATblock - A procedure block
- A
DOblock with theTRANSACTIONkeyword orON ERRORphrase
The basic syntax for the UNDO
statement is:
|
In the following example code, a transaction is started at the Customer level and Order changes are done in a subtransaction:
|
UNDO as an
option on a DO, FOR, or REPEAT block. In the
following example code, upon encountering an error, the current block is undone and
execution resumes in the code following the block.
|
You can also specify UNDO, LEAVE label, if you want to leave a specified
transaction block identified by label, upon
encountering the condition. See the LEAVE statement for more detail on using a label with
LEAVE.