fc2ブログ

(元)社内SEの徒然なる日記

NetCOBOLでORA-01405が発生

Nullは使えない

先日、久しぶりにNetCOBOLで新規にプログラムを作成したのですが、見事にエラーが発生しました。

SQLCAの中身を確認したところ、下記の状態になっていました。

SQLCODE : -000001405
SQLERRM : ORA-01405: フェッチした列の値がNULLです

SQLERRD(3) : +000000001
SQLWARN0 :
SQLWARN1 :
SQLWARN2 :
SQLWARN3 :
SQLWARN4 :
SQLWARN5 :
SQLWARN6 :
SQLWARN7 :


あぁ、NetCOBOLってNULL値を受け取れないんだったよ。

状況

実行したSQLは、こんな感じ。
NUMMGRがNUMBER型、NUMRCDがVARCHAR2型です。

SELECT
ABCD.NUMMGR , -- 管理番号
ABCD.NUMRCD -- 記録番号
FROM
ABCD
WHERE
ABCD.NUMMGR = 123456


フェッチでする変数はこんなのです。
H-NUMMGRがS9タイプ、H-NUMRCDがXタイプです。

EXEC SQL
FETCH CU1
INTO
:H-NUMMGR , -- 管理番号
:H-NUMRCD -- 記録番号
END-EXEC.


この条件下で、ABCD.NUMRCDがNull値の時にフェッチを行うと、エラーが発生しました。

対応

まぁ、Nullを受けられないのであれば、別の値の変更すれば良いだけの話です。
という訳で、こんな感じにSQLを修正します。

SELECT
NVL(ABCD.NUMMGR, 0) , -- 管理番号
NVL(RTRIM(ABCD.NUMRCD), ' ') -- 記録番号
FROM
ABCD
WHERE
ABCD.NUMMGR = 123456


NVL関数で、Null値の時に違う値に置き換えています。
ABCD.NUMMGRは数値型なので、単純に0に置き換えています。
ABCD.NUMRCDは文字型なので、RTRIM関数で右側空白を除去した上で、NVL関数で半角スペースに置き換えています。

RTRIM関数は無くても良さそうですけど、こいつをDML文で使用する時には意味が出てきます。

更新とかで使う場合

問題があるとすれば、フェッチした値を更新で使用する場合です。
ABCD.NUMRCDの値がNull値だったとした時に、下記のUPDATE文が実行されたとします。

UPDATE ABCD
SET
ABCD.NUMMGR = :H-NUMMGR, -- 管理番号
ABCD.NUMRCD = :H-NUMRCD -- 記録番号
WHERE
ABCD.NUMMGR = 123456


ホスト変数「H-NUMRCD」には半角スペースが入っているので、このまま更新を行うと値がNullからスペースに置き換わってしまいます。

※ 置き換わるはず。試してないけど、たしか変わったはず...

なので、さらにRTRIM関数をかぶせて、スペースをNull値に変換して、Null値のままで更新されるようにします。

UPDATE ABCD
SET
ABCD.NUMMGR = NVL(:H-NUMMGR,) + 1 , -- 管理番号
ABCD.NUMRCD = RTRIM(:H-NUMRCD) -- 記録番号
WHERE
ABCD.NUMMGR = 123456


これで、問題なく動作します。

まぁ、元のデータが固定長で、後方にスペースがある事が前提とかなってくると、RTRIM関数を使うのはまずいですよね。その時は、COBOL側で工夫するしかないでしょうね。

標識変数

今回はNVL関数を使用する方法を使いましたが、Oracleのマニュアルでは「標識変数」という変数を使用してNull値の発生を記録うんぬんって書いています。

これは、フェッチした値がNull値かそうじゃないかを表すフラグを項目別に用意、フェッチした時にNull値であった場合には、そのフラグに-1が設定されるので、それでNullの判断をしてねっていうものです。

言葉だけ聞くと使えそうな気もするのですが、実際に使った感想としては、変数の準備とか、判定用のIF文とかで無駄にソースが長くなるだけで使いにくいと思いました。

Null値の判定がどうしても必要な処理でない限り、無理に使う事もないでしょうね。
ということで、使い方の説明もしません。必要な方は、頑張ってNetCOBOLとかのマニュアルを開いて下さい。

スポンサードリンク

PageTop

コメント


管理者にだけ表示を許可する