Site logo
Tác giả
  • avatar Nguyễn Đức Xinh
    Name
    Nguyễn Đức Xinh
    Twitter
Ngày xuất bản
Ngày xuất bản

Embedded SQL trong COBOL: Hiểu về Pro*COBOL và khối EXEC SQL

Embedded SQL (Pro*COBOL) là gì?

Trong hệ thống COBOL enterprise, business logic thường phải đọc/ghi dữ liệu trong relational database như Oracle. Thay vì tự viết các database call mức thấp, ta dùng Embedded SQL: các câu lệnh SQL được viết bên trong source COBOL, được đánh dấu bằng EXEC SQL ... END-EXEC.

Pro*COBOL là precompiler của Oracle hiểu các Embedded SQL này. Nó:

  • Quét chương trình COBOL.
  • Tìm tất cả block EXEC SQL ... END-EXEC.
  • Dịch mỗi block thành lời gọi COBOL native tới Oracle runtime library.

Sau đó, bạn compile file COBOL đã được sinh ra bằng COBOL compiler như bình thường.

Về khái niệm:

  • Bạn viết: COBOL + SQL trong các block EXEC SQL.
  • Pro*COBOL dịch Embedded SQL → các lời gọi procedure COBOL.
  • COBOL compiler chỉ thấy code COBOL chuẩn.

Lợi ích:

  • COBOL xử lý control flow, batch, file I/O.
  • SQL xử lý truy vấn dữ liệu quan hệ, transaction, join, aggregate.

Ví dụ chương trình dùng ba Embedded SQL quan trọng:

  • EXEC SQL COMMIT WORK RELEASE END-EXEC.
  • EXEC SQL ROLLBACK WORK RELEASE END-EXEC.
  • EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.

Ba câu này điều khiển transaction boundaryerror handling.

Pro*COBOL precompiler hoạt động như thế nào?

Từ source trộn (COBOL + SQL) đến COBOL thuần

Flow build điển hình:

  1. Viết source PROGRAM.PCO:
    • Chứa câu lệnh COBOL.
    • Chứa Embedded SQL:
EXEC SQL
    SELECT COL1 INTO :WS-COL1
    FROM   MY_TABLE
    WHERE  KEY = :WS-KEY
END-EXEC.
  1. Chạy Pro*COBOL precompiler:

    • Input: PROGRAM.PCO.
    • Output: PROGRAM.CBL.
    • Mỗi block EXEC SQL được thay bằng code COBOL + lời gọi Oracle runtime.
  2. Compile bằng COBOL compiler (nhìn thấy COBOL thuần).

  3. Link và run: executable dùng Oracle library để gửi SQL xuống DB.

Developer chủ yếu suy nghĩ ở mức COBOL + SQL, không phải ở mức call API thấp.

Cú pháp cơ bản: EXEC SQL ... END-EXEC

Mọi Embedded SQL đều bọc như sau:

EXEC SQL
    <SQL statement or directive>
END-EXEC.
  • EXEC SQL / END-EXEC đánh dấu biên block SQL.
  • Bên trong bạn viết SQL.
  • Dùng host variable (biến COBOL) với prefix : để trao đổi dữ liệu.

Ví dụ:

WORKING-STORAGE SECTION.
01  WS-EMP-NO          PIC 9(5).
01  WS-EMP-NAME        PIC X(30).

PROCEDURE DIVISION.
MOVE 12345 TO WS-EMP-NO.

EXEC SQL
    SELECT EMP_NAME
      INTO :WS-EMP-NAME
      FROM EMPLOYEES
     WHERE EMP_NO = :WS-EMP-NO
END-EXEC.

DISPLAY 'Employee name: ' WS-EMP-NAME.
  • WS-EMP-NO, WS-EMP-NAME là host variable COBOL.
  • :WS-EMP-NO, :WS-EMP-NAME là cách SQL thấy các biến đó.

Ba Embedded SQL statement quan trọng

EXEC SQL COMMIT WORK RELEASE END-EXEC.
EXEC SQL ROLLBACK WORK RELEASE END-EXEC.
EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC.

1. COMMIT WORK RELEASE

EXEC SQL
    COMMIT WORK RELEASE
END-EXEC.
  • COMMIT WORK: ghi nhận tất cả thay đổi kể từ lần COMMIT gần nhất.
  • RELEASE: đóng kết nối DB, giải phóng resource.

Dùng cho:

  • Cuối chương trình khi không cần DB nữa.
  • Job chạy lâu, muốn chủ động đóng session.

Nếu chỉ COMMIT WORK mà không RELEASE, session vẫn mở.

2. ROLLBACK WORK RELEASE

EXEC SQL
    ROLLBACK WORK RELEASE
END-EXEC.
  • ROLLBACK WORK: huỷ toàn bộ thay đổi kể từ lần commit thành công trước đó.
  • RELEASE: đóng session.

Dùng khi:

  • Xảy ra lỗi nghiêm trọng.
  • Không thể tiếp tục xử lý an toàn.
IF ERROR-FLAG = 'Y'
    EXEC SQL
        ROLLBACK WORK RELEASE
    END-EXEC
    GO TO ABEND-ROUTINE
END-IF.

3. WHENEVER SQLERROR CONTINUE

EXEC SQL
    WHENEVER SQLERROR CONTINUE
END-EXEC.
  • Báo cho Pro*COBOL: nếu có SQL error, tiếp tục trong COBOL, không nhảy đi đâu khác.

Một số directive khác:

  • WHENEVER SQLERROR STOP
  • WHENEVER SQLERROR GOTO label
  • WHENEVER SQLERROR PERFORM paragraph

Dùng CONTINUE khi bạn muốn tự xử lý lỗi bằng cách kiểm tra SQLCODE.

Ví dụ:

EXEC SQL
    WHENEVER SQLERROR CONTINUE
END-EXEC.

EXEC SQL
    INSERT INTO ORDERS (ORDER_ID, AMOUNT)
    VALUES (:WS-ORDER-ID, :WS-AMOUNT)
END-EXEC.

IF SQLCODE NOT = 0
    MOVE 'Y' TO ERROR-FLAG
    MOVE 'INSERT FAILED' TO ERROR-MESSAGE
    PERFORM LOG-ERROR-PROC
END-IF.

Bảng tóm tắt 3 câu lệnh

SQL Statement Mục đích
EXEC SQL COMMIT WORK RELEASE END-EXEC Ghi nhận mọi thay đổi DB và disconnect sạch sẽ
EXEC SQL ROLLBACK WORK RELEASE END-EXEC Huỷ thay đổi từ lần commit gần nhất và disconnect
EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC Bỏ xử lý lỗi tự động; cho phép tự xử lý lỗi trong COBOL

Using host variable trong Embedded SQL

  • Host variable khai báo trong DATA DIVISION.
  • Dùng :VAR-NAME trong block EXEC SQL.

Ví dụ:

WORKING-STORAGE SECTION.
01  WS-CUST-ID       PIC 9(10).
01  WS-CUST-NAME     PIC X(50).
01  WS-SQLCODE       PIC S9(9) COMP-5.

EXEC SQL INCLUDE SQLCA END-EXEC.
MOVE 1001 TO WS-CUST-ID.

EXEC SQL
    SELECT CUST_NAME
      INTO :WS-CUST-NAME
      FROM CUSTOMERS
     WHERE CUST-ID = :WS-CUST-ID
END-EXEC.

MOVE SQLCODE TO WS-SQLCODE.

IF WS-SQLCODE = 0
    DISPLAY 'Customer Name: ' WS-CUST-NAME
ELSE
    DISPLAY 'SQL ERROR: ' WS-SQLCODE
END-IF.
  • SQLCA chứa SQLCODE sau mỗi câu lệnh SQL.

Pattern transaction control trong Pro*COBOL

MAIN-PROC.
    EXEC SQL
        WHENEVER SQLERROR CONTINUE
    END-EXEC

    PERFORM OPEN-CONNECTION-PROC
    PERFORM PROCESS-ALL-RECORDS
    PERFORM TERMINATE-PROC
    GOBACK.
  • Trong PROCESS-ALL-RECORDS, thường xuyên kiểm tra ERROR-FLAG, SQLCODE.
  • Commit định kỳ (ví dụ mỗi 100 hoặc 1000 record).
  • Khi lỗi nghiêm trọng, ROLLBACK WORK RELEASE và đi vào đoạn ABEND.

So sánh Embedded SQL với các cách tích hợp khác

Aspect Embedded SQL (Pro*COBOL) COBOL File I/O Middleware / API ngoài
Data source Relational DB (Oracle, ...) Sequential/VSAM file Web service, message queue, API
Syntax SQL trong EXEC SQL ... END-EXEC READ, WRITE, REWRITE CALL tới API
Schema management DBMS quản lý Định nghĩa trong COBOL Phụ thuộc contract API
Transactions COMMIT / ROLLBACK đảm bảo ACID Thường tự xử lý Phụ thuộc middleware/protocol
Tooling SQL*Plus, AWR, công cụ DB File utility, sort/merge API gateway, monitoring
Use case OLTP, báo cáo, query phức tạp, integrity mạnh Batch, log, staging Tích hợp hệ thống, microservice

Best practice khi dùng Embedded SQL

  • Tách business logic và SQL operation vào các paragraph nhỏ.
  • Luôn kiểm tra SQLCODE (hoặc SQLSTATE) sau câu lệnh quan trọng.
  • Dùng COMMIT/ROLLBACK có chủ đích, không commit từng record nếu không cần.
  • Dùng COMMIT WORK RELEASE hoặc ROLLBACK WORK RELEASE ở cuối job hoặc đường đi lỗi.
  • Log lỗi với đủ context: SQLCODE, message, key (ORDER-ID, CUSTOMER-ID, ...).

Ví dụ tổng hợp

IDENTIFICATION DIVISION.
PROGRAM-ID. LOAD-ORDERS.

DATA DIVISION.
WORKING-STORAGE SECTION.
01  WS-ORDER-ID          PIC 9(10).
01  WS-AMOUNT            PIC S9(9)V99 COMP-3.
01  WS-RECORD-COUNT      PIC 9(5) VALUE ZERO.
01  WS-ERROR-FLAG        PIC X     VALUE 'N'.

EXEC SQL INCLUDE SQLCA END-EXEC.

PROCEDURE DIVISION.
MAIN-PROC.
    EXEC SQL
        WHENEVER SQLERROR CONTINUE
    END-EXEC

    PERFORM OPEN-FILES
    PERFORM PROCESS-ORDERS
    PERFORM CLOSE-FILES

    IF WS-ERROR-FLAG = 'N'
        EXEC SQL
            COMMIT WORK RELEASE
        END-EXEC
    ELSE
        EXEC SQL
            ROLLBACK WORK RELEASE
        END-EXEC
    END-IF

    GOBACK.

Ví dụ này minh hoạ Embedded SQL, manual error handling và transaction control trong một job COBOL.