COBOL - 数据库接口



到目前为止,我们已经学习了在 COBOL 中使用文件的方法。现在,我们将讨论 COBOL 程序如何与 DB2 交互。它涉及以下术语:

  • 嵌入式 SQL
  • DB2 应用程序编程
  • 主机变量
  • SQLCA
  • SQL 查询
  • 游标

嵌入式 SQL

嵌入式 SQL 语句用于 COBOL 程序中执行标准 SQL 操作。在应用程序程序编译之前,嵌入式 SQL 语句由 SQL 处理器预处理。COBOL 被称为宿主语言。COBOL-DB2 应用程序是指包含 COBOL 和 DB2 的应用程序。

嵌入式 SQL 语句的工作方式与普通 SQL 语句类似,但有一些细微的差别。例如,查询的输出被定向到一组预定义的变量,这些变量称为主机变量。在 SELECT 语句中添加了 INTO 子句。

DB2 应用程序编程

以下是编写 COBOL-DB2 程序时需要遵循的规则:

  • 所有 SQL 语句必须用EXEC SQLENDEXEC分隔。

  • SQL 语句必须在 B 区编码。

  • 程序中使用的所有表都必须在 WorkingStorage 部分声明。这是通过使用INCLUDE语句完成的。

  • 除了 INCLUDE 和 DECLARE TABLE 之外的所有 SQL 语句都必须出现在 Procedure Division 中。

主机变量

主机变量用于接收来自表的数据或将数据插入表中。必须为要在程序和 DB2 之间传递的所有值声明主机变量。它们在 Working-Storage 部分声明。

主机变量不能是组项,但可以组合到主机结构中。它们不能重命名重新定义。在 SQL 语句中使用主机变量时,在其前面加上冒号 (:)

语法

以下是声明主机变量并在 Working-Storage 部分包含表的语法:

DATA DIVISION.
   WORKING-STORAGE SECTION.
   
   EXEC SQL
   INCLUDE table-name
   END-EXEC.

   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.

SQLCA

SQLCA 是一个 SQL 通信区域,通过它 DB2 将 SQL 执行的反馈传递给程序。它告诉程序执行是否成功。SQLCA 下有一些预定义的变量,例如SQLCODE,其中包含错误代码。SQLCODE 中的值“000”表示执行成功。

语法

以下是声明 Working-Storage 部分的 SQLCA 的语法:

DATA DIVISION.
WORKING-STORAGE SECTION.
	EXEC SQL
	INCLUDE SQLCA
	END-EXEC.

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 SQL
      INCLUDE SQLCA
   END-EXEC.
   
   EXEC SQL
      INCLUDE STUDENT
   END-EXEC.
   
   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.

PROCEDURE DIVISION.
   EXEC SQL
      SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS
      INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS FROM STUDENT
      WHERE STUDENT-ID=1004
   END-EXEC.
   
   IF SQLCODE = 0 
      DISPLAY WS-STUDENT-RECORD
   ELSE DISPLAY 'Error'
   END-IF.
STOP RUN.

执行上述 COBOL 程序的JCL

//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 SQL
   INCLUDE SQLCA
   END-EXEC.
   
   EXEC SQL
   INCLUDE STUDENT
   END-EXEC.
   
   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.

PROCEDURE DIVISION.
   MOVE 1005 TO WS-STUDENT-ID.
   MOVE 'TutorialsPoint' TO WS-STUDENT-NAME.
   MOVE 'Hyderabad' TO WS-STUDENT-ADDRESS.
   
   EXEC SQL
      INSERT 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-REC
   ELSE DISPLAY 'Error'
   END-IF.
STOP RUN.

执行上述 COBOL 程序的JCL

//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 SQL
   INCLUDE SQLCA
   END-EXEC.
   
   EXEC SQL
   INCLUDE STUDENT
   END-EXEC.
   
   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.

PROCEDURE DIVISION.
   MOVE 'Bangalore' TO WS-STUDENT-ADDRESS.
   EXEC SQL
      UPDATE STUDENT SET STUDENT-ADDRESS=:WS-STUDENT-ADDRESS
      WHERE STUDENT-ID = 1003
   END-EXEC.
   
   IF SQLCODE = 0 
      DISPLAY 'Record Updated Successfully'
   ELSE DISPLAY 'Error'
   END-IF.
STOP RUN.

执行上述 COBOL 程序的JCL

//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 SQL
   INCLUDE SQLCA
   END-EXEC.
   
   EXEC SQL
   INCLUDE STUDENT
   END-EXEC.
   
   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.

PROCEDURE DIVISION.
   MOVE 1005 TO WS-STUDENT-ID.
   
   EXEC SQL
      DELETE FROM STUDENT
      WHERE STUDENT-ID=:WS-STUDENT-ID
   END-EXEC.
   
   IF SQLCODE = 0 
      DISPLAY 'Record Deleted Successfully'
   ELSE DISPLAY 'Error'
   END-IF.
STOP RUN.

执行上述 COBOL 程序的JCL

//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

游标

游标用于一次处理多个行选择。它们是保存查询所有结果的数据结构。它们可以在 Working-Storage 部分或 Procedure Division 中定义。以下是与游标相关的操作:

  • 声明
  • 打开
  • 关闭
  • 提取

声明游标

游标声明可以在 Working-Storage 部分或 Procedure Division 中完成。第一个语句是 DECLARE 语句,它是一个非可执行语句。

EXEC SQL
   DECLARE STUDCUR CURSOR FOR
   SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENT
   WHERE STUDENT-ID >:WS-STUDENT-ID
END-EXEC.

打开

在使用游标之前,必须执行 Open 语句。Open 语句准备执行 SELECT。

EXEC SQL
   OPEN STUDCUR
END-EXEC.

关闭

Close 语句释放游标占用的所有内存。在结束程序之前关闭游标是强制性的。

EXEC SQL
   CLOSE STUDCUR
END-EXEC.

提取

Fetch 语句识别游标并将值放入 INTO 子句中。Fetch 语句在循环中编码,因为我们一次获取一行。

EXEC SQL
   FETCH STUDCUR
   INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS
END-EXEC.

以下示例显示了如何使用游标从 STUDENT 表中提取所有记录:

IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO.

DATA DIVISION.
   WORKING-STORAGE SECTION.
   
   EXEC SQL
   INCLUDE SQLCA
   END-EXEC.
   
   EXEC SQL
   INCLUDE STUDENT
   END-EXEC.
   
   EXEC SQL BEGIN DECLARE SECTION
   END-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 SECTION
   END-EXEC.
   
   EXEC SQL
      DECLARE STUDCUR CURSOR FOR
      SELECT STUDENT-ID, STUDENT-NAME, STUDENT-ADDRESS FROM STUDENT
      WHERE STUDENT-ID >:WS-STUDENT-ID
   END-EXEC.

PROCEDURE DIVISION.
   MOVE 1001 TO WS-STUDENT-ID.
   PERFORM UNTIL SQLCODE = 100
   
   EXEC SQL
      FETCH STUDCUR
      INTO :WS-STUDENT-ID, :WS-STUDENT-NAME, WS-STUDENT-ADDRESS
   END-EXEC
   
   DISPLAY WS-STUDENT-REC
END-PERFORM	
STOP RUN.

执行上述 COBOL 程序的JCL

//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
广告