FETCH Cursor


FETCH statement retrieves the current positioned row data and assigns it to the corresponding variable(s)/host variable(s).

FETCH statement is also responsible for repositioning the cursor to the next sequential row in the result table.

FETCH statement can retrieve one row at a time.

FETCH statement should have an INTO clause with host variable(s) or variable(s) to place the data retrieved.

Updatable (WITH HOLD) cursors use the current row's concept and update or delete it using WHERE CURRENT OF phase.

The order of host variables in the FETCH statement should be the same as the order of the columns specified in DECLARE CURSOR.

Syntax -


EXEC SQL
	FETCH FROM cursor-name/cursor-variable-name
	INTO
	:variable-for-col1,
	:variable-for-col2,
	.
	.
	:variable-for-coln
END-EXEC.

cursor-name -

  • Cursor-name is the name of the cursor used in an application program to refer to the cursor.
  • The cursor-name should be unique in the entire application program.
  • The max length of the cursor-name is 30 characters for the cursors declared WITH RETURN.
  • The max length of the cursor-name is 128 characters for the standard cursors.

cursor-variable-name -

  • Cursor-variable-name is a working-storage variable that contains the cursor name used in an application program to refer to the cursor.
  • The cursor-variable-name should be unique in the entire application program.
  • The max length of the cursor-name is 30 characters for the cursors declared WITH RETURN.
  • The max length of the cursor-name is 128 characters for the standard cursors.

INTO clause -

  • INTO clause identifies one or more target variables for assigning output values.
  • The value assignments perform in the same order how the columns are specified in DECLARE CURSOR. i.e., The first column in the DECLARE CURSOR value is assigned to the first target variable in the FETCH, the second column value to the second target variable, and so on.
  • Suppose any error occurs at the specific variable in the sequence. In that case, the variables before the error variable have the assigned values, and those after the error variable have no values.
  • If the target variables in FETCH are less in number than the table columns in the DECLARE, then the value "W" is assigned to the SQLWARN3 field of the SQLCA.

variable-for-col1, variable-for-col2, .... -

  • These variables are used to receive the data from the database table.
  • Every variable should have an equivalent COBOL declaration for the corresponding DB2 table column type.

  • Variable-for-col* can be a global-variable, host-variable, SQL-parameter, SQL-variable, transition-variable, array-variable, or field-reference.
  • Host-variables from table DCLGEN are generally used to receive the table's data and avoid compatibility issues.

NULL Indicator -


While fetching the data, there might be a chance that the data might not be available in the source table. The column contains the value which is other than actual data called "NULL".

Suppose any NULL valued column exists in the retrieved columns list. In that case, the NULL indicator variable should code along with the host variable.

Suppose the NULL indicator variable is not coded with FETCH and the column returns a NULL value. In that case, the FETCH will fail with a -305 error.

The NULL indicator variables can always declare with –NI at the end of the field name.

The declaration of the NULL indicator is S9(04) COMP.

The NULL indicator variable handling in FETCH statement syntax as shown below -

Syntax -


EXEC SQL
	FETCH FROM cursor-name/cursor-variable-name
	INTO
	:variable-for-col1
	:variable-for-col1-NI,
	:variable-for-col2
	:variable-for-col2-NI,
	.
	.
	:variable-for-coln
END-EXEC.

The NULL indicator validation for the value is valid or NULL is shown below -

IF host-variable-col-ni = -1 (NULL value received from table column)
                        = 0  (Received valid value)
                        = 1  (Received truckated value)

Cursor positioning -


An open cursor has the below three possible positions -

  • Before a row
  • On a row
  • After the last row.

If a cursor is on a row of the result table, that row is called the cursor's current row. The current row is referenced in an UPDATE or DELETE statement.

If the cursor is positioned or any row except the last row -

  • The SQLCODE is set to 0.
  • It repositions on the next row, and the values of that row are assigned to the target variables.

If the cursor is currently positioned on or after the last row of the result table -

  • The SQLCODE is set to +100, and SQLSTATE is set to '02000'.
  • The cursor positions after the last row.
  • Values are not assigned to the target variables.

If the cursor state is unpredictable, an error occurs.

Examples -


Scenario1 - Fetch cursor for retrieving two columns.

Code -

 EXEC SQL 
	FETCH F1
	 INTO :HV1,
	      :HV2
   END-EXEC.

Scenario2 - Fetch cursor for retrieving two columns with NULL indicator check.

Code -

  EXEC SQL 
	FETCH F2
	 INTO :HV1
	      :HV1-NI,
	      :HV2
	      :HV2-NI
   END-EXEC.

Scenario3 - FETCH statement uses an SQLDA.

Code -

EXEC SQL 
	FETCH F3
	USING DESCRIPTOR :sqlda3
   END-EXEC.

Scenario4 - Fetch cursor using a variable that contains cursor name for retrieving two columns.

Code -

Declaration-  05 WS-CS-VAR     PIC X(10) VALUE "F4".
EXEC SQL 
	FETCH WS-CS-VAR
	 INTO :HV1,
	      :HV2
   END-EXEC.

Practical Example -


Scenario - The below example describes how the cursor is declared and used in the COBOL + DB2 program.

Requirement - Display employees id, name, designation from department 1000.

Input -

employee_details table

CURSOR Example Code -

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
***************************** Top of Data ******************************
       IDENTIFICATION DIVISION.                                         
       PROGRAM-ID. CREADONL.                                            
                                                                        
       ENVIRONMENT DIVISION.                                            
       DATA DIVISION.                                                   
       WORKING-STORAGE SECTION.                                         
                                                                        
           EXEC SQL                                                     
             INCLUDE SQLCA                                              
           END-EXEC.                                                    
                                                                        
           EXEC SQL                                                     
             INCLUDE EMPLDET                                            
           END-EXEC.                                                    
                                                                        
      * DECLARING CURSOR                                                
                                                                        
           EXEC SQL                                                     
                DECLARE CSR1 CURSOR FOR                                 
                SELECT EMP_ID,                                          
                       EMP_NAME,                                        
                       DESIGNATION                                      
                FROM   EMPLOYEE_DETAILS                                 
                WHERE  DEPT_ID = 1000                                   
                FOR    FETCH ONLY                                       
           END-EXEC.                                                    
                                                                        
       PROCEDURE DIVISION.                                              
                                                                        
      * OPENING CURSOR                                                  
                                                                        
           EXEC SQL                                                     
                OPEN CSR1                                               
           END-EXEC.                                                    
                                                                        
      * FETCHING CURSOR LOOP UNTIL END OF RESULT TABLE                  
                                                                        
           IF SQLCODE EQUAL ZERO                                        
              PERFORM FETCH-EMP-DETAILS                                 
                 THRU FETCH-EMP-DETAILS-EXIT                            
                UNTIL SQLCODE NOT EQUAL 0                               
           END-IF.                                                      
                                                                        
      * CLOSING CURSOR                                                  
                                                                        
           EXEC SQL                                                     
                CLOSE CSR1                                              
           END-EXEC.                                                    
                                                                        
           STOP RUN.                                                    
                                                                        
       FETCH-EMP-DETAILS.                                               
                                                                        
      * FETCH CURSOR                                                    
                                                                        
           EXEC SQL                                                     
                FETCH CSR1                                              
                INTO   :EMP-ID,                                         
                       :EMP-NAME,                                       
                       :DESIGNATION                                     
           END-EXEC.                                                    
                                                                        
           EVALUATE SQLCODE                                             
               WHEN ZERO                                                
                    DISPLAY  EMP-ID, "|", EMP-NAME, "|",                
                             DESIGNATION                                
               WHEN 100                                                 
                    CONTINUE                                            
               WHEN OTHER                                               
                    DISPLAY "DB2 ERROR:  ", SQLCODE                     
           END-EVALUATE.                                                
                                                                        
       FETCH-EMP-DETAILS-EXIT.                                          
           EXIT.                                                        
**************************** Bottom of Data ****************************

Output -

CURSOR Program Output