Controlling the size of a transaction
- Last Updated: February 14, 2024
- 3 minute read
- OpenEdge
- Version 12.2
- Documentation
You have already learned which statements start a transaction automatically. To summarize, these are:
-
FOR EACHblocks that directly update the database -
REPEATblocks that directly update the database - Procedure blocks or user-defined functions that directly update the database
-
DOblocks with theON ERRORorON ENDKEYqualifiers (which you'll learn more about later) that contain statements that update the database
You can also control the size of a transaction by adding the TRANSACTION keyword to a DO,
FOR EACH, or REPEAT block.
This can force a transaction to be larger, but because of the statements that start a
transaction automatically, you cannot use it to make a transaction smaller than ABL otherwise
would make it.
The following example shows how transaction blocks are affected by changes to
the procedure. As written, there is a DO TRANSACTION block
around the whole update of both the Order and any
modified OrderLines:
|
Since DO blocks do not have the block
transaction property, any changes made in the DO block (Order
update block) scope to the containing transaction block, in this case the DO TRANSACTION block. Any errors that occur within the DO block cause the entire transaction to be backed out.
FOR EACH
OrderLine starts a new subtransaction for each iteration. If
an error occurs within the FOR EACH block, only the change
made for that iteration is backed out. Any changes for any previous iterations, as well as any
changes made in the DO block, are committed to the database.
To verify this, generate a listing file the same way you did previously:

When you run this COMPILE statement, your
listing file tells you, among other things, where all the transactions begin and end. This is
very valuable information. You should always use a listing file in any complex procedure to
make sure that your record scope and transaction scope are as you intended.
If you want any error that occurs while updating an OrderLine record to undo the Order updates as
well, then FOR EACH OrderLine should be rewritten as
follows:
|
The error will be thrown into the containing DO
TRANSACTION block and cause that block to undo, thus undoing the entire
transaction.
Taking a look at this listing file, you can see that the DO TRANSACTION block is a top-level block within its procedure,
marked with a 1. The DO block inside it, where the Order is actually updated, is block level 2:
|
Further down, you can see that the FOR EACH
block that operates on the OrderLines is also a nested
block, at level 2 within the main DO TRANSACTION block:
|
Now if you look at the end of the file, you see a summary of all the blocks. Here's an excerpt from that part of the listing. It shows that the procedure blocks for the internal procedures fetchOrder and saveOrder are not transaction blocks:
|
This is a good thing. You never want your transactions to default to the level of a procedure, because they are likely to be larger than you want them to be. This means that record locks are held longer than necessary and that more records might be involved in a transaction than you intended.
Next you see that the AVM identifies the first DO block at line 144 as a transaction block. This is because it has an explicit
TRANSACTION qualifier on it. The nested DO block two lines later is not a transaction block because a
DO block by itself does not mark a transaction.
The FOR EACH block at line 164 is also
marked as a transaction block:
|
What does this mean? Is this really a separate transaction? The answer is no,
because the FOR EACH block is nested inside the larger
DO TRANSACTION block. This code tells you that the FOR EACH block would be a transaction block (because this is the
nature of FOR EACH blocks that perform updates). However,
because it is nested inside a larger transaction, it becomes a subtransaction. The AVM can back out changes made in a subtransaction within a larger
transaction when an error occurs, and you can also do this yourself, as described in the Subtransactions.