COBOL 数据库接口
截至目前,我们已经学会了使用COBOL中的文件。现在,我们将讨论COBOL程序如何与DB2进行交互。它涉及以下术语:
- Embedded SQL(嵌入式SQL)
- DB2 Application Programming(DB2应用程序编程)
- Host Variables(宿主变量)
- SQLCA
- SQL Queries(SQL查询)
- Cursors(游标)
Embedded SQL(嵌入式SQL)
嵌入式SQL语句用于COBOL程序中以执行标准的SQL操作。在编译应用程序之前,嵌入式SQL语句由SQL处理器进行预处理。COBOL被称为Host Language(宿主语言)。 COBOL-DB2应用程序是包括COBOL和DB2的应用程序。
嵌入式SQL语句的工作原理与普通的SQL语句类似,但有一些小变化。例如,查询的输出定向到被称为**Host Variables(宿主变量)**的预定义变量集合。另外,INTO子句是放置在SELECT语句中。
DB2 Application Programming (DB2应用程序编程)
以下是编写COBOL-DB2程序时要遵循的规则:
- 所有SQL语句在EXEC SQL和END-EXEC之间必须分隔。
- SQL语句必须在区域B中进行编码
- 程序中使用的所有表必须在工作存储节(working-storage section)中声明。这是通过使用INCLUDE语句来完成的。
- 除了INCLUDE和DECLARE TABLE之外的所有SQL语句都必须出现在过程部中。
Host Variables(宿主变量)
宿主变量用于从表中接收数据或在表中插入数据。必须为在程序和DB2之间传递的所有值声明宿主变量。它们在工作存储节中进行声明。
宿主变量不能是组项,但它们可能在宿主结构中组合在一起。它们不能被重命名或重定义。将宿主变量与SQL语句一起使用,给它们添加前缀冒号(?。
语法
以下是在工作存储节中声明宿主变量并包含表的语法:
DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE table-nameEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 STUDENT-REC.05 STUDENT-ID PIC 9(4).05 STUDENT-NAME PIC X(25).05 STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.
SQLCA
SQLCA是一个SQL通信区域,通过它DB2将SQL执行的反馈传递给程序。它告诉程序执行是否成功。在SQLCA下有一些预定义变量,如SQLCODE,其中包含错误代码。SQLCODE中的值“000”表示成功执行。
语法
以下是在工作存储节中声明SQLCA的语法:
DATA DIVISION.
WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.
SQL Queries(SQL查询)
假设我们有一个名为“Student”的表,其中包含Student-Id,Student-Name和Student-Address。
STUDENT表包含以下数据:
Student Id Student Name Student Address
1001 Mohtashim M. Hyderabad
1002 Nishant Malik Delhi
1003 Amitabh Bachan Mumbai
1004 Chulbul Pandey Lucknow
以下示例显示了COBOL程序中SELECT查询的用法:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE STUDENTEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-STUDENT-REC.05 WS-STUDENT-ID PIC 9(4).05 WS-STUDENT-NAME PIC X(25).05 WS-STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.PROCEDURE DIVISION.EXEC SQLSELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESSINTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS FROM STUDENTWHERE STUDENT-ID=1004END-EXEC.IF SQLCODE=0 DISPLAY WS-STUDENT-RECORDELSE DISPLAY 'Error'END-IF.
STOP RUN.
JCL执行上述COBOL程序:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS=A,MSGCLASS=C
//STEP001 EXEC PGM=IKJEFT01
//STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *DSN SYSTEM(SSID)RUN PROGRAM(HELLO) PLAN(PLANNAME) -END
/*
当你编译和执行上面的程序,会产生以下结果:
1004 Chulbul Pandey Lucknow
以下示例显示了COBOL程序中INSERT查询的用法:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE STUDENTEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-STUDENT-REC.05 WS-STUDENT-ID PIC 9(4).05 WS-STUDENT-NAME PIC X(25).05 WS-STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.PROCEDURE DIVISION.MOVE 1005 TO WS-STUDENT-ID.MOVE 'TutorialsPoint' TO WS-STUDENT-NAME.MOVE 'Hyderabad' TO WS-STUDENT-ADDRESS.EXEC SQLINSERT INTO STUDENT(STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS)VALUES (:WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS)END-EXEC.IF SQLCODE=0 DISPLAY 'Record Inserted Successfully'DISPLAY WS-STUDENT-RECELSE DISPLAY 'Error'END-IF.
STOP RUN.
JCL执行上述COBOL程序。
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS=A,MSGCLASS=C
//STEP001 EXEC PGM=IKJEFT01
//STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *DSN SYSTEM(SSID)RUN PROGRAM(HELLO) PLAN(PLANNAME) -END
/*
当你编译和执行上面的程序,会产生以下结果:
Record Inserted Successfully
1005 TutorialsPoint Hyderabad
以下示例显示了COBOL程序中UPDATE查询的用法:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE STUDENTEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-STUDENT-REC.05 WS-STUDENT-ID PIC 9(4).05 WS-STUDENT-NAME PIC X(25).05 WS-STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.PROCEDURE DIVISION.MOVE 'Bangalore' TO WS-STUDENT-ADDRESS.EXEC SQLUPDATE STUDENT SET STUDENT-ADDRESS=:WS-STUDENT-ADDRESSWHERE STUDENT-ID=1003END-EXEC.IF SQLCODE=0 DISPLAY 'Record Updated Successfully'ELSE DISPLAY 'Error'END-IF.
STOP RUN.
JCL执行上述COBOL程序:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS=A,MSGCLASS=C
//STEP001 EXEC PGM=IKJEFT01
//STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *DSN SYSTEM(SSID)RUN PROGRAM(HELLO) PLAN(PLANNAME) -END
/*
当你编译和执行上面的程序,会产生以下结果:
Record Updated Successfully
以下示例显示了COBOL程序中DELETE查询的用法:
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.DATA DIVISION.
WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE STUDENTEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-STUDENT-REC.05 WS-STUDENT-ID PIC 9(4).05 WS-STUDENT-NAME PIC X(25).05 WS-STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.PROCEDURE DIVISION.MOVE 1005 TO WS-STUDENT-ID.EXEC SQLDELETE FROM STUDENTWHERE STUDENT-ID=:WS-STUDENT-IDEND-EXEC.IF SQLCODE=0 DISPLAY 'Record Deleted Successfully'ELSE DISPLAY 'Error'END-IF.
STOP RUN.
JCL执行上述COBOL程序:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS=A,MSGCLASS=C
//STEP001 EXEC PGM=IKJEFT01
//STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *DSN SYSTEM(SSID)RUN PROGRAM(HELLO) PLAN(PLANNAME) -END
/*
当你编译和执行上面的程序,会产生以下结果:
Record Deleted Successfully
Cursors(游标)
游标用于一次处理多个行选择。它们是保存查询的所有结果的数据结构,可以在工作存储节或过程部中定义。以下是与游标相关的操作:
- Declare(声明)
- Open(打开)
- Close(关闭)
- Fetch(提取)
Declare Cursor(声明游标)
游标声明可以在工作存储节或过程部中完成。第一个语句是DECLARE语句,是一个不可执行语句。
EXEC SQLDECLARE STUDCUR CURSOR FORSELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENTWHERE STUDENT-ID >:WS-STUDENT-ID
END-EXEC.
Open(打开)
在使用游标之前,必须执行Open语句。Open语句为执行准备了SELECT。
EXEC SQLOPEN STUDCUR
END-EXEC.
Close(关闭)
Close语句释放游标占用的所有内存。在结束程序之前必须关闭游标。
EXEC SQLCLOSE STUDCUR
END-EXEC.
Fetch(提取)
Fetch语句标识游标并将值放在INTO子句中。Fetch语句是循环编码的,因此我们一次可获取一行。
EXEC SQLFETCH STUDCURINTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS
END-EXEC.
以下示例显示了游标从STUDENT表中提取所有记录的用法:
IDENTIFICATION DIVISION.PROGRAM-ID. HELLO.DATA DIVISION.WORKING-STORAGE SECTION.EXEC SQLINCLUDE SQLCAEND-EXEC.EXEC SQLINCLUDE STUDENTEND-EXEC.EXEC SQL BEGIN DECLARE SECTIONEND-EXEC.01 WS-STUDENT-REC.05 WS-STUDENT-ID PIC 9(4).05 WS-STUDENT-NAME PIC X(25).05 WS-STUDENT-ADDRESS X(50).EXEC SQL END DECLARE SECTIONEND-EXEC.EXEC SQLDECLARE STUDCUR CURSOR FORSELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENTWHERE STUDENT-ID >:WS-STUDENT-IDEND-EXEC.PROCEDURE DIVISION.MOVE 1001 TO WS-STUDENT-ID.PERFORM UNTIL SQLCODE = 100EXEC SQLFETCH STUDCURINTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESSEND-EXECDISPLAY WS-STUDENT-RECEND-PERFORM STOP RUN.
JCL执行上述COBOL程序:
//SAMPLE JOB(TESTJCL,XXXXXX),CLASS=A,MSGCLASS=C
//STEP001 EXEC PGM=IKJEFT01
//STEPLIB DD DSN=MYDATA.URMI.DBRMLIB,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *DSN SYSTEM(SSID)RUN PROGRAM(HELLO) PLAN(PLANNAME) -END
/*
当你编译和执行上面的程序,会产生以下结果:
1001 Mohtashim M. Hyderabad
1002 Nishant Malik Delhi
1003 Amitabh Bachan Mumbai
1004 Chulbul Pandey Lucknow