# ISAM Statements
> [HTML Version](isamstatements.htm)
**ISAM #ch, code, key**
**Parameters**
_ch_ ([Num](num.htm.md)) \[in\]
Channel number specified in the OPEN statement for the file. Note that a single channel is used for the combination of the IDA and the primary IDX. Secondary IDX files have their own channels.
_key _ ([String](string.htm.md)) \[in/out\]
A symbolic key
_code_ ([Num](num.htm.md)) \[in\]
A numeric code 1-8 indicating the operation to perform.
| **Code** | **Operation** | **Description** |
|------|------|------|
| 1 | Lookup | Searches the IDX file associated with CH for the specified KEY. If not found, returns ERF(ch) = 33. Else returns ERF(ch) = 0 and sets the relative record number variable (from the OPEN statement) to match the found record. |
| 2 | Get Next | Performs a get-next operation based on index position left by the previous 1, 2, or 7 statement. Sets the relative record number variable to match the fund record. Sets ERF(ch) to 38 if no more keys in sequence. KEY is not used. Generally superseded by code 7. |
| 3 | Add Key | Adds the specified key to the index, associating it with the record number currently stored in the record number variable. |
| 4 | Delete Key | Deletes the specified key from the index. |
| 5 | Add Record | Allocates/assigns a new record in the IDA file, returning its relative record number in the record number variable. Must be followed by a WRITE\{L\} #ch, rec statement to actually write the record data to the file. |
| 6 | Delete Record | Deletes the record specified by the relative record number variable from the IDA file (adding it back to the deleted record chain so that it may be reused). |
| 7 | Get Next | Same as code 2 except returns the found next key in the KEY variable. |
| 8 | Get Previous | A-Shell extension, added in 6.1.1344.0. Reverse of code 7. Returns ERF(ch) = 38 if no more keys (i.e. when you hit the start of the index). |
**Error processing**
Each of the ISAM statements returns a status which you should check using the [ERF()](filefunctions.htm.md) function. The range of values is given in the table below:
| **ERF() value** | **Meaning** |
|------|------|
| 32 | Illegal ISAM statement code |
| 33 | Key not found during key lookup |
| 34 | Duplicate key during attempt to add key. Note that duplicate keys not supported by ISAM 1.x. |
| 35 | IDX is corrupted and must be recreated. |
| 36 | IDX file full. You've disabled the auto-expand feature (see NOAUTOX option), the disk is full, or you've reached the maximum limit of 4 billion IDX blocks. |
| 37 | IDA file full. You've disabled the auto-expand feature (see NOAUTOX), the disk is full, or you've reached the maximum limit of 4 billion records.) |
| 38 | End of file reached during get-next key operation, or start of file reached during get-previous key operation |
| 39 | Illegal ISAM sequence. See File Locking below. |
**File Locking**
You must employ some kind of file locking system when allowing multi-user access to ISAM files (i.e. when the files are opened in INDEXED rather than INDEXED'EXCLUSIVE mode). Unlike ISAM-A, ISAM 1.x provides you the latitude (and responsibility) to implement the locking system. However, when [LOKSER](lokser_sp.htm.md) is enabled, it will be used and certain rules will be enforced with violations resulting in ERF(ch) returning error 39. The following table summarizes the ISAM / LOKSER behavior and rules:
| **Stmt Code** | **Operation** | **Primary IDX** | **Secondary IDX** |
|------|------|------|------|
| 1, 2, 7, 8 | Locate record by key | Locked automatically and remains locked on return | Locked automatically during operation but unlocked on return |
| 3 | Add key | Must be locked initially (typically from a previous locate record operation). Unlocked on return | Locked automatically during operation; unlocked on return |
| 4 | Delete Key | Must be locked initially and remains locked on return | Locked automatically during operation; unlocked on return |
| 5 | Add Data Rec | Must be locked initially; remains locked on return | Not applicable |
| 6 | Delete Data Rec | Must be locked initially; remains locked on return | Not applicable |
| READ | read data | Must be locked initially; unlocked on return | Not applicable |
| READL | read/lock (for update) | Must be locked initially; remains locked on return | Not applicable |
| WRITE | write/update data | Must be locked initially; unlocked on return. | Not applicable |
| WRITEL | write new data | Must be locked initially; remains locked on return. (Normally followed by Add Key which unlocks) | Not applicable |
| LOCK | Lock primary index | Locked by operation | Not applicable |
| UNLOKR | Unlock record and/or index | Unlocked by operation (no harm if already unlocked) | Not applicable |
**Examples**
The following samples illustrate some typical operations on an ISAM file with a single primary IDX. For simplicity, all the examples use a generic routine called ISAM'ERROR for any unexpected errors. The routine should always start with an UNLOKR #CH to make sure the file isn't left in a locked state.
**Add Record:**
ISAM #CH, 1, KEY \! lookup key
IF ERF(CH) = 0 THEN
? "Record already exists"
UNLOKR #CH
ELSEIF ERF(CH) # 33 THEN \! any state other than not-found
GOTO ISAM'ERROR
ELSE
ISAM #CH, 5, KEY \! add a data record
IF ERF(CH) # 0 THEN
GOTO ISAM'ERROR
ELSE
WRITEL #CH, REC \! write the data
ISAM #CH, 3, KEY \! add the key
IF ERF(CH) # 0 THEN
GOTO ISAM'ERROR
ENDIF
ENDIF
ENDIF
**Delete Record:**
ISAM #CH, 1, KEY \! lookup key
IF ERF(CH) = 33 THEN
? "Record doesn't exist"
UNLOKR #CH
ELSEIF ERF(CH) # 0 THEN
GOTO ISAM'ERROR
ELSE
READL #CH, REC \! read/lock the record
ISAM #CH, 4, KEY \! delete key
IF ERF(CH) # 0 THEN
GOTO ISAM'ERROR
ELSE
ISAM #CH, 6, KEY \! delete the data record
IF ERF(CH) # 0 THEN
GOTO ISAM'ERROR
ENDIF
ENDIF
ENDIF
**Read Record:**
ISAM #CH, 1, KEY \! lookup key
IF ERF(CH) = 0 THEN \! if found ...
READ #CH, REC \! read rec (unlocks index)
ELSE \! else
? "Key ";KEY;" not found" \!
UNLOKR #CH \! manually unlock index
ENDIF
**Subtopics**
-