【実務・中級編】DB2埋め込みSQLにおけるEXEC SQL INCLUDE SQLCAの役割 – PL/Iの基本構文とデータ制御実践ガイド

PL/Iの「予約語なし」という自由と、SQLCAが教える「エラーハンドリングの真髄」

若手の諸君、現場でPL/Iのソースを追っていて、「なぜこの変数名はこんなに自由なんだ?」と驚いたことはないか。あるいは、DB2の埋め込みSQLで `EXEC SQL INCLUDE SQLCA` を書くとき、単なる「おまじない」だと思っていないだろうか。

今日は、メインフレームの深淵を覗くPL/Iの基本と、実務で絶対に外してはならないSQLCAの扱いについて、少し熱く語らせてもらう。

1. 識別子(変数名)の「自由」という名の罠

PL/Iの最大の特徴、それは「予約語が存在しない」ということだ。`IF` も `THEN` も `ELSE` も、PL/Iにおいてはコンテキスト(文脈)で判断される。つまり、変数名として `IF` を定義しても、コンパイラは文脈を読んで正しく処理してくれる。

だが、覚えておいてほしい。「できること」と「やるべきこと」は違う。
かつて、変数名に予約語を多用して書かれた古いソースの改修で、私がどれほど泣きを見たか。可読性は保守性の命だ。識別子は常に `WK-CUSTOMER-ID` のように、ハイフンを用いて意味が通る名前を付けるのが、この業界の暗黙の正義である。

2. EXEC SQL INCLUDE SQLCA:DB2との対話の要

DB2埋め込みSQLを使う際、必ず `EXEC SQL INCLUDE SQLCA` を置く。これは、プリコンパイラがDB2とのやり取りの結果(成功か失敗か、何行処理したか)を格納するための「共通領域」をソースに埋め込む作業だ。

これを忘れると、SQLが失敗してもプログラムは平然と動き続け、翌朝の運用担当者が真っ青になるような不整合データがデータベースに残ることになる。

実装パターン:SQLCODEの監視とONユニットの活用

PL/Iの醍醐味は `ON` ユニットだ。エラー発生時にプログラムを異常終了させるのではなく、適切にキャッチしてログを残し、クリーンに終了させるのがプロの仕事である。

/i
/ ————————————————————- /
/ DB2エラーハンドリングの標準実装パターン /
/ ————————————————————- /
EXEC SQL INCLUDE SQLCA;

DCL W_SQLCODE_MSG CHAR(80) VARYING;

/ エラー発生時の強制的な制御フロー /
ON CONDITION(DB2_ERROR) BEGIN;
PUT SKIP LIST(‘!!! DB2 ERROR DETECTED !!!’);
PUT SKIP LIST(‘SQLCODE IS:’, SQLCODE);
/ 適切なロールバック処理 /
EXEC SQL ROLLBACK;
STOP;
END;

/ SQL実行後のチェックルーチン /
CHECK_SQL: PROC;
IF SQLCODE ^= 0 THEN DO;
IF SQLCODE = 100 THEN
PUT SKIP LIST(‘対象データなし’);
ELSE
SIGNAL CONDITION(DB2_ERROR);
END;
END CHECK_SQL;

3. VSAMとDB2が混在する現場の「作法」

我々が扱うシステムでは、VSAMファイルからデータを読み込み、DB2を更新するようなバッチが主役だ。ここで気をつけてほしいのが、PL/Iのレコード入出力とDB2の整合性だ。

`READ FILE(INPUT_VSAM) INTO(REC_BUFFER);` で読み込んだ後、その内容をDB2に書き込む際は、必ず `SQLSTATE` を確認すること。`SQLSTATE` は `SQLCODE` よりもポータブルで、エラーの性質(警告か致命的か)を詳細に教えてくれる。

実践的なコーディングのコツ

1. インデントの徹底: `IF-THEN-ELSE` や `DO-END` のブロック構造は、必ず視覚的に階層がわかるようにインデントすること。
2. BUILTIN関数の活用: 文字列操作には `SUBSTR` や `INDEX` を積極的に使うこと。手書きのループで文字を探すのは、バグの温床でしかない。
3. 大文字記述の原則: メインフレームのソースは、今でも大文字ベースが主流だ。小文字混じりのコードは、エディタのシンタックスハイライトが効かない環境では、ただのノイズになる。

/i
/ VSAMから読んだ値をDB2へ挿入する例 /
READ FILE(VSAM_IN) INTO(VSAM_REC);
IF VSAM_REC.STATUS = ‘A’ THEN DO;
EXEC SQL INSERT INTO TBL_CUST
(CUST_ID, CUST_NAME)
VALUES (:VSAM_REC.ID, :VSAM_REC.NAME);

/ SQLSTATEチェック (00000は成功) /
IF SQLSTATE ^= ‘00000’ THEN DO;
PUT SKIP LIST(‘INSERT失敗: ‘ || SQLSTATE);
CALL CHECK_SQL;
END;
END;

最後に:諸君へ送るエール

PL/Iは古臭い言語だと言う奴もいる。だが、数十年前に書かれたコードが今もなお、日本の金融や物流を支えているという事実こそが、この言語の堅牢さと設計思想の正しさを証明している。

仕様書の隅っこに書かれた `SQLCA` の重要性に気づくこと。コンパイラ任せにするのではなく、自分がどうエラーを制御し、どうシステムを安全に着陸させるか。その視点を持つだけで、諸君の書くコードは一変するはずだ。

困ったことがあれば、いつでもまた聞きに来い。デバッグの秘訣は、常に「一番ありえない場所」に潜んでいるものだ。現場からは以上だ。

タイトルとURLをコピーしました