Establish another key with which to search a table

A part table is usually searched with a part number as the key. To enter order information when the part number is missing from the order, the part name may be used as an alternate key for searching the table.

PARTNO is a table on the tableBASE library and its key is Part Number. The PARTNO table is opened and an Alternate Index called PARTNAME is Invoked with the key of Part Name. This now allows access to either the PARTNAME table or the PARTNO table, two routes to the same data.

Note:
The Invoke Alternate (IA) command has been largely superseded by Open commands (OR and OW) that are capable of opening multiple Alternate Indexes for a single Data Table. However, the IA command remains the only way to generate a transient Alternate Index.
In COBOL
 DATA DIVISION.
 01  PART-ROW.
     05  PART-NUMBER                            PIC X(10).
     05  PART-NAME                              PIC X(25).
     05  PART-FIELDS...                         
 01  ORDER-PART-NAME                            PIC X(25) VALUE SPACES.
 01  ORDER-PART-NUMBER                          PIC X(10) VALUE SPACES.
 01  PARTNO-COMMAND-AREA.
     05  PARTNO-COMMAND                         PIC XX    VALUE SPACES.
     05  PARTNO-TABLE                           PIC X(8)  VALUE 'PARTNO'.
     05  PARTNO-FOUND                           PIC X     VALUE SPACES.
     05  PARTNO-INDIRECT-IND                    PIC X     VALUE LOW-VALUES.
     05  PARTNO-RESERVED                        PIC X     VALUE LOW-VALUES.
     05  PARTNO-ABEND-OVERRIDE                  PIC X     VALUE SPACES.
     05  PARTNO-ERROR-CODE                      PIC S9(4) COMP VALUE +0.
     05  PARTNO-COUNT                           PIC S9(9) COMP VALUE +0.
     05  PARTNO-LOCK                            PIC X(8)  VALUE SPACES.
     05  PARTNO-LENGTHS.
         10  PARTNO-ROW-OVERRIDE-LENGTH         PIC S9(9) COMP VALUE +0.
         10  PARTNO-ROW-ACTUAL-LENGTH           PIC S9(9) COMP VALUE +0.
         10  PARTNO-FG-KEY-LENGTH               PIC S9(4) COMP VALUE +0.
     05  PARTNO-FUNCTION-ID                     PIC S9(4) COMP VALUE +0.
     05  PARTNO-FUNCTION-AREA                   PIC X(8)  VALUE LOW-VALUES.
     05  PARTNO-DATE-AREA             REDEFINES PARTNO-FUNCTION-AREA.
         10  PARTNO-DATE                        PIC X(8).
         10  RESERVED                           PIC X(20).
     05  PARTNO-RETURNED-ABS-GEN-NO             PIC S9(4) COMP VALUE +0.
     05  PARTNO-ERROR-SUBCODE                   PIC S9(4) COMP VALUE +0.
     
 01  PARTNAME-COMMAND-AREA.
     05  PARTNAME-COMMAND                       PIC XX    VALUE SPACES.
     05  PARTNAME-TABLE                         PIC X(8)  VALUE 'PARTNAME'.
     05  PARTNAME-FOUND                         PIC X     VALUE SPACES.
     05  PARTNAME-INDIRECT-IND                  PIC X     VALUE LOW-VALUES.
     05  PARTNAME-RESERVED                      PIC X     VALUE LOW-VALUES.
     05  PARTNAME-ABEND-OVERRIDE                PIC X     VALUE SPACES.
     05  PARTNAME-ERROR-CODE                    PIC S9(4) COMP VALUE +0.
     05  PARTNAME-COUNT                         PIC S9(9) COMP VALUE +0.
     05  PARTNAME-LENGTHS.
         10  PARTNAME-ROW-OVERRIDE-LENGTH       PIC S9(9) COMP VALUE +0.
         10  PARTNAME-ROW-ACTUAL-LENGTH         PIC S9(9) COMP VALUE +0.
         10  PARTNAME-FG-KEY-LENGTH             PIC S9(4) COMP VALUE +0.
     05  PARTNAME-FUNCTION-ID                   PIC S9(4) COMP VALUE +0.
     05  PARTNAME-FUNCTION-AREA                 PIC X(8)  VALUE LOW-VALUES.
     05  PARTNAME-DATE-AREA           REDEFINES PARTNAME-FUNCTION-AREA.
         10  PARTNAME-DATE                      PIC X(8).
         10  RESERVED                           PIC X(20).
     05  PARTNAME-RETURNED-ABS-GEN-NO           PIC S9(4) COMP VALUE +0.
     05  PARTNAME-ERROR-SUBCODE                 PIC S9(4) COMP VALUE +0.

 01  PARTNAME-ALT-DEFINITION.
     05  PARTNAME-ORG                           PIC X     VALUE 'S'.
     05  PARTNAME-METHOD                        PIC X     VALUE 'B'.
     05  PARTNAME-KEY-COUNT                     PIC S9(4) COMP VALUE +1.
     05  PARTNAME-KEY-LOCATION                  PIC S9(9) COMP VALUE +11.
     05  PARTNAME-KEY-SIZE                      PIC S9(9) COMP VALUE +25.

 PROCEDURE DIVISION.
 HOUSE-KEEPING.

***  GET PARTNO TABLE FROM TABLE BASE LIBRARY.

     MOVE 'OR'                                  TO PARTNO-COMMAND
     CALL 'TBLBASE'                       USING TB-PARM
                                                PARTNO-COMMAND-AREA

***  INVOKE THE ALTERNATE INDEX. THIS CAUSES THE ALTERNATE
***  INDEX TO BE CREATED ON THE PARTNO TABLE.

     MOVE 'IA'                                  TO PARTNAME-COMMAND
     CALL 'TBLBASE'                       USING TB-PARM
                                                PARTNAME-COMMAND-AREA
                                                PARTNO-TABLE
                                                PARTNAME-ALT-DEFINITION
 PROCESSING.
 
***  TO SEARCH FOR A VALID PARTNO WITH PART-NO AS A KEY, USE:
     MOVE 'SK'                                  TO PARTNO-COMMAND
     CALL 'TBLBASE'                       USING TB-PARM
                                                PARTNO-COMMAND-AREA
                                                ORDER-PART-NUMBER

***  TO FETCH A PARTNO USING PART NAME AS A KEY INTO PARTNAME, USE:
     MOVE 'FK'                                  TO PARTNAME-COMMAND
     CALL 'TBLBASE'                       USING TB-PARM
                                                PARTNAME-COMMAND-AREA
                                                PART-ROW
                                                ORDER-PART-NAME
In C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "dkh.h"

/*
 * DK1TEX6C
 *
 * Establish another key with which to search a table.
 */
 
/*
 * Assume these are user inputs.
 */
static char szTableName[6] = "AARON";
static char szAltTableName[9] = "AARALT  ";
static char szStatus[6] = "NYYYN";
static char szReadPassword[2] = " ";
static int nGen = 0;
static char szKey[6] = "TIGER";
static char szSecondKey[16] = "123456789012345";
static int nRowSize = 20;
static int nKeySize = 5;
static int nSecondKeySize = 15;

int main(void)
{
    TbParmStruct tbParm;
    TbCommandAreaStruct tbCommArea;
    TbCommandAreaStruct tbCommArea1;
    TbTableDefinitionStruct tbTableDef;
    TbAltDefinitionStruct tbAltDef;
    char sReadPassword[8];
    char * pRowArea = NULL;
    char * pKeyArea = NULL;
    char * pSecondKeyArea = NULL;
    char sStatus[8];
    char sTableName[8];
    int nGeneration = nGen;
    
    /*
     * Initialize the parameters.
     */
    fixStringLength( szTableName, sTableName, 8 );
    InitTbParm( &tbParm );
    InitTbCommandArea( &tbCommArea, sTableName );
    InitTbCommandArea( &tbCommArea1, sTableName );
    InitTableDef( &tbTableDef );
    InitAltDefinitionStruct( &tbAltDef );

    /*
     * Initialize tableBASE with CS, ChangeStatus.
     */
    fixStringLength( szStatus, sStatus, 8 );
    memcpy( tbCommArea.tbCommand, "CS", 2 );
    TBLBASE( &tbParm, &tbCommArea, sStatus );
    if( tbCommArea.tbError != TB_SUCCESS )
    {
        printf( "CS\n");
        printf( "Found code: %c\n", tbCommArea.tbFound );
        printf( "Error code: %d\n", tbCommArea.tbError );
        printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
        return tbCommArea.tbError;
    }
    
    tbAltDef.org = 'U';
    tbAltDef.method = 'S';
    tbAltDef.keyLocation = 6;
    tbAltDef.keySize = 15;
    
    /*
     * Open the table for read with OR.
     */
    fixStringLength( szReadPassword, sReadPassword, 8 );
    memcpy( tbCommArea.tbCommand, "OR", 2 );
    TBLBASE( &tbParm, &tbCommArea, sReadPassword, nGeneration);
    if( tbCommArea.tbError != TB_SUCCESS )
    {
        printf( "OW\n");
        printf( "Found code: %c\n", tbCommArea.tbFound );
        printf( "Error code: %d\n", tbCommArea.tbError );
        printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
        return tbCommArea.tbError;
    }
    
    /*
     * Create a temporary Alternate Index with IA (InvokeAlternate).
     * For performance reasons, it is better to use a different
     * TbCommandAreaStruct for each table and for each index.
     */
    fixStringLength( szAltTableName, tbCommArea1.tbTable, 8 );
    memcpy( tbCommArea1.tbCommand, "IA", 2 );
    TBLBASE( &tbParm, &tbCommArea1, sTableName, &tbAltDef );
    if( tbCommArea1.tbError != TB_SUCCESS )
    {
        printf( "IA\n");
        printf( "Found code: %c\n", tbCommArea1.tbFound );
        printf( "Error code: %d\n", tbCommArea1.tbError );
        printf( "Sub code: %d\n", tbCommArea1.tbErrorSubcode );
        return tbCommArea1.tbError;
    }
    
    /*
     * Allocate spaces for the keys and the row.
     */
    pRowArea = (char *) malloc( nRowSize + 1 );
    if( pRowArea == NULL )
        return TB_ERROR;
    memset( pRowArea, ' ', nRowSize );
    pKeyArea = (char *) malloc( nKeySize );
    if( pKeyArea == NULL )
    {
        free( pRowArea );
        return TB_ERROR;
    }
    memset( pKeyArea, ' ', nKeySize );
    pSecondKeyArea = (char *) malloc( nSecondKeySize );
    if( pSecondKeyArea == NULL )
    {
        free( pRowArea );
        free( pKeyArea );
        return TB_ERROR;
    }
    memset( pSecondKeyArea, ' ', nSecondKeySize );
    
    /*
     * Search by Key (SK) using the Data Table.
     */
    fixStringLength( szKey, pKeyArea, nKeySize );
    memcpy( tbCommArea.tbCommand, "SK", 2 );
    TBLBASE( &tbParm, &tbCommArea, pKeyArea );
    if( tbCommArea.tbError != TB_SUCCESS || tbCommArea.tbFound != 'Y' )
    {
        printf( "SK\n");
        printf( "Found code: %c\n", tbCommArea.tbFound );
        printf( "Error code: %d\n", tbCommArea.tbError );
        printf( "Sub code: %d\n", tbCommArea.tbErrorSubcode );
        free( pRowArea );
        free( pKeyArea );
        free( pSecondKeyArea );
        return tbCommArea.tbError;
    }
    else
    {
        printf( "Found code: %c\n", tbCommArea.tbFound );
    }
    
    /*
     * Fetch by Key (FK) using the secondary index.
     */
    fixStringLength( szSecondKey, pSecondKeyArea, nSecondKeySize );
    memcpy( tbCommArea1.tbCommand, "FK", 2 );
    /* Call TableBASE */
    TBLBASE( &tbParm, &tbCommArea1, pRowArea, pSecondKeyArea );
    if( tbCommArea1.tbError != TB_SUCCESS || tbCommArea1.tbFound != 'Y' )
    {
        printf( "FK\n");
        printf( "Found code: %c\n", tbCommArea1.tbFound );
        printf( "Error code: %d\n", tbCommArea1.tbError );
        printf( "Sub code: %d\n", tbCommArea1.tbErrorSubcode );
        free( pRowArea );
        free( pKeyArea );
        free( pSecondKeyArea );
        return tbCommArea1.tbError;
    }
    else
    {
        pRowArea[nSecondKeySize] = '\0';
        printf( "Row found by second key: %s\n", pRowArea );
    }
    
    if( pRowArea != NULL )
        free( pRowArea );
    if( pKeyArea != NULL )
        free( pKeyArea );
    if( pSecondKeyArea != NULL )
        free( pSecondKeyArea );
        
    return TB_SUCCESS;
}