update changes a record, write adds one and delete removes one. This page covers the syntax, the file declaration each needs, which record update and delete act on, the %fields form, what happens when write meets a duplicate key, and the file status codes you can test.
It is a focused page. The short entry for each file operation is in the RPGLE File I/O Opcodes Reference, reading one record and its lock is in the RPGLE CHAIN Opcode Reference, and the functions that report errors are in the RPGLE File and Error BIFs Reference.
The examples are free-form RPGLE. They use a keyed file with the key fields CUSTKEY and ORDNO and the field ORDSTS, which holds three records: C0001 / 1, C0001 / 2 and C0002 / 3, all with status N.
dcl-f ordWork keyed usage(*update : *delete : *output) extfile('*LIBL/ORDERW') rename(ORDERW : ordRec);
dcl-ds keyDs likerec(ordRec : *key);
dcl-ds ordData likerec(ordRec : *all);
Syntax
update{(E)} name {data-structure | %fields(name{:name...})};
write{(E)} name {data-structure};
delete{(EHMR)} {search-arg} name;
| Opcode | What it does | Operand notes |
|---|---|---|
update | Rewrites the last locked record that was read | For an externally described file, name is the record format of the record that was read |
write | Adds a new record built from the current field values | name is a record format, or a program-described file |
delete | Removes a record | With no search argument it removes the current record. With a key it removes the record with that key |
Each takes the (E) extender, and delete also takes H, M and R when the search argument is a list or %kds. The (E) extender and the ER indicator are alternatives, and you cannot code both.
The file declaration
The usage keyword on dcl-f decides which operations the file allows.
| Usage | Allows |
|---|---|
*input | The read and position operations only |
*update | The input operations and update |
*delete | delete, and it must be named in a free-form declaration |
*output | write |
In free-form code, *update does not make a file delete-capable. Name *delete as well. To add records to a file that is also read or updated, name *output too, as the declaration above does. The older fixed-format entry U implied delete, so code converted from it needs *delete added.
UPDATE
update rewrites the last locked record that an input operation retrieved from the file. Change the fields, then name the record format.
keyDs.CUSTKEY = 'C0001';
keyDs.ORDNO = 2;
chain %kds(keyDs) ordWork;
if %found(ordWork);
ORDSTS = 'S';
update ordRec;
endif;
The current values of all the fields in the record format are written back, so a field you did not change is written with the value it had when you read it. Test %found first, because there is no record to change after a chain that found nothing.
Which record can be updated
Situation before update | Result |
|---|---|
A chain, read, reade, readp or readpe that returned a record and locked it | Allowed |
The read used (n) | Not allowed. The record is not locked |
| The read failed or reached end of file | Not allowed. Read the record again with locking |
Another operation on the same file between the read and the update | Not allowed. IBM says none should be performed |
Two update operations in a row | Not allowed. Read the record again first |
name is not the record format that was last read | Error |
An update with no prior successful read fails with status 1221, update operation attempted without a prior read.
Update some fields
To change only some fields, name them in %fields. IBM says to use %fields when only some of the fields of a record are to be updated.
chain %kds(keyDs) ordWork;
if %found(ordWork);
ORDSTS = 'H';
update ordRec %fields(ORDSTS);
endif;
Update from a data structure
Read into a data structure and update from it. Define it with likerec on the same record format. For update, the second parameter can be *input, *output or *all, or omitted.
chain %kds(keyDs) ordWork ordData;
if %found(ordWork);
ordData.ORDSTS = 'S';
update ordRec ordData;
endif;
WRITE
write adds a record built from the current values of all the fields in the record format. It does not need a prior read. The file must be declared with *output.
CUSTKEY = 'C0003';
ORDNO = 4;
ORDSTS = 'N';
write ordRec;
To write from a data structure, define it with likerec(ordRec : *output) or *all.
dcl-ds newRec likerec(ordRec : *output);
newRec.CUSTKEY = 'C0003';
newRec.ORDNO = 5;
newRec.ORDSTS = 'N';
write ordRec newRec;
Duplicate keys
If the file has unique keys and the key already exists, the write fails with status 1021. Code (e) and test %error, then read the status.
CUSTKEY = 'C0001';
ORDNO = 1;
ORDSTS = 'N';
write(e) ordRec;
if %error;
// %status(ordWork) is 1021: a record with this key already exists
endif;
Without (e) or ER, the error goes to the program’s default file error handling.
DELETE
delete removes a record permanently. The file must be declared with *delete. There are two forms.
After a chain or a read, name the record format to remove the record that was just read. The record must have been locked by that input operation.
keyDs.CUSTKEY = 'C0003';
keyDs.ORDNO = 4;
chain %kds(keyDs) ordWork;
if %found(ordWork);
delete ordRec;
endif;
With a search argument, delete finds and removes the record with that key, and %found says whether there was one.
keyDs.CUSTKEY = 'C0003';
keyDs.ORDNO = 5;
delete %kds(keyDs) ordRec;
if not %found(ordWork);
// no record had that key
endif;
On IBM i, a read after a successful delete returns the record after the deleted one, so a delete inside a read loop does not skip a record.
Status codes to handle
Code (e) and test %error, then use %status for the code. These are the codes in the IBM i 7.5 reference that apply to disk file changes.
| Status | Meaning | Typical cause |
|---|---|---|
| 1021 | A record that already exists was written | write of a duplicate key in a file with unique keys |
| 1022 | Referential constraint error | write, update or delete that breaks a constraint |
| 1023, 1024 | Error in a trigger program, before or after the operation | A trigger on the file failed |
| 1218 | Record already locked | A read or chain of a record that another job holds |
| 1221 | Update attempted without a prior read | update with no locked record |
UPDATE, WRITE and DELETE compared
update | write | delete | |
|---|---|---|---|
| Needs a prior locked read | Yes | No | Only without a search argument |
| Usage keyword | *update | *output | *delete |
| Names | The record format last read | A record format | A record format or file, with a key or not |
| Result test | %error with (e) | %error with (e) | %found with a key, %error with (e) |
Common mistakes
- Calling
updateafterchain(n)orread(n), or after a read that found nothing. - Declaring
*updateand expectingdeleteto work. Free-form code needs*delete. - Writing to a file declared without
*output. - Not coding
(e)where a duplicate key is possible, so the program ends on status 1021. - Doing another operation on the file between the read and the
update. - Updating twice from one read.
- Using
deletewith a key but without testing%found.
FAQ
Which record does UPDATE change?
The last record that a locking input operation retrieved from that file. Nothing else should be done on the file in between.
How do I change only one field?
Change the field, then code update ordRec %fields(ORDSTS); with the fields you want written.
What happens when WRITE finds a duplicate key?
In a file with unique keys, status 1021 is set. Without (e) or an ER indicator, the default file error handling takes over. With (e), test %error.
Summary
updaterewrites the last locked record read,writeadds a record, anddeleteremoves the current record or the record with a given key.- Declare the file with
*update,*outputand*deleteas needed. Free-form code must name*delete. - Read with a lock, change the fields, then
update. Use%fieldsto limit the fields written. - Code
(e)where a duplicate key or a lock is possible, and test%errorand%status. - For reading and positioning, see the RPGLE READ, READE and READP Opcode Reference and the RPGLE SETLL and SETGT Opcode Reference, and for the other file operations the RPGLE File I/O Opcodes Reference.