CLPでデータ・ベースを更新する方法があるだろうか?
CLPでデータ・ベースは DCLFで定義しておけば
RCVFコマンドでレコード単位で読取ることができることは
よく知られている。
しかし SNDFコマンドでレコードをCLPで出力することはできない。
SNDFが使える対象は画面ファイル(DSPF)だけである。
しかしCLPでもデータ・ベースを更新できる方法はひとつだけある。
それはVer7.1で利用可能になったRUNSQLコマンドを使うことである。
RUNSQLコマンドとはVer7.1で追加されたSQL命令を実行する
コマンドであり SELECT文は実行できないが UPDATE/INSERT/DELETEを
実行することができる。
それでは RUNSQLによってレコードを更新するサンブルCLPを紹介しよう。
[商品マスターのレコードをSQLで更新するサンプル: TESTSQLC1 ]
ソースはこちらで
001.00 PGM 002.00 /*-------------------------------------------------------------------*/ 003.00 /* TESTSQLC1 : SQL レコード更新 */ 004.00 /* */ 005.00 /* 2020/02/29 作成 */ 006.00 /*-------------------------------------------------------------------*/ 007.00 DCL VAR(&MSG) TYPE(*CHAR) LEN(132) 008.00 DCL VAR(&MSGID) TYPE(*CHAR) LEN(7) 009.00 DCL VAR(&MSGF) TYPE(*CHAR) LEN(10) 010.00 DCL VAR(&MSGFLIB) TYPE(*CHAR) LEN(10) 011.00 DCL VAR(&MSGDTA) TYPE(*CHAR) LEN(132) 012.00 DCL VAR(&TYPE) TYPE(*CHAR) LEN(1) 013.00 DCL VAR(&TOPGMQ) TYPE(*CHAR) LEN(10) 014.00 DCL VAR(&MSGTYPE) TYPE(*CHAR) LEN(10) + 015.00 VALUE('*ESCAPE ') 016.00 DCL VAR(&APIERR) TYPE(*CHAR) LEN(116) + 017.00 VALUE(X'000074') /* 2 進数 */ 018.00 DCL VAR(&NULL4) TYPE(*CHAR) LEN(4) + 019.00 VALUE(X'00000000') 020.00 /*( SQL レコード更新用の変数 )*/ 021.00 DCL VAR(&STR) TYPE(*CHAR) LEN(1024) 022.00 MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR)) 023.00 0024.00 /*( 環境の取得 )*/ 0025.00 RTVJOBA TYPE(&TYPE) 0026.00 IF COND(&TYPE *EQ '0') THEN(DO) /* バッチ */ 0027.00 CHGVAR VAR(&TOPGMQ) VALUE('*SYSOPR ') 0028.00 ENDDO /* バッチ */ 0029.00 ELSE CMD(DO) /* 対話式 */ 0030.00 CHGVAR VAR(&TOPGMQ) VALUE('*TOPGMQ ') 0031.00 ENDDO /* 対話式 */ 0032.00 0033.00 /*( SQL によるレコード更新 )*/ 0034.00 CHGVAR VAR(&STR) VALUE('UPDATE QTRFIL/SHOHIN SET + 0035.00 SHTANK = 28000 WHERE SHCODE = ''SF-SDCD''') 0036.00 RUNSQL SQL(&STR) COMMIT(*NONE) 0037.00 CHGVAR VAR(&MSG) VALUE('1 レコードを更新しました。 ') 0038.00 GOTO SNDMSG 0039.00 RETURN 0040.00 0041.00 APIERR: 0042.00 CHGVAR VAR(&MSGID) VALUE(%SST(&APIERR 9 7)) 0043.00 CHGVAR VAR(&MSGDTA) VALUE(%SST(&APIERR 17 100)) 0044.00 CHGVAR VAR(&MSGF) VALUE('QCPFMSG ') 0045.00 CHGVAR VAR(&MSGFLIB) VALUE('QSYS ') 0046.00 GOTO SNDMSG 0047.00 0048.00 ERROR: RCVMSG MSGTYPE(*LAST) RMV(*NO) MSG(&MSG) + 0049.00 MSGDTA(&MSGDTA) MSGID(&MSGID) MSGF(&MSGF) + 0050.00 MSGFLIB(&MSGFLIB) 0051.00 SNDMSG: IF COND(&MSGID *EQ ' ') THEN(DO) 0052.00 SNDPGMMSG MSGID(CPF9897) MSGF(QCPFMSG) MSGDTA(&MSG) + 0053.00 TOMSGQ(&TOPGMQ) MSGTYPE(&MSGTYPE) 0054.00 MONMSG MSGID(CPF2400) EXEC(RETURN) 0055.00 ENDDO 0056.00 ELSE CMD(DO) 0057.00 SNDPGMMSG MSGID(&MSGID) MSGF(&MSGFLIB/&MSGF) + 0058.00 MSGDTA(&MSGDTA) TOMSGQ(&TOPGMQ) + 0059.00 MSGTYPE(&MSGTYPE) 0060.00 MONMSG MSGID(CPF2400) EXEC(RETURN) 0061.00 ENDDO 0062.00 ENDPGM
[解説]
SQL文の文字ストリング &STR に次のように値をセットしている。
0034.00 CHGVAR VAR(&STR) VALUE('UPDATE QTRFIL/SHOHIN SET + 0035.00 SHTANK = 28000 WHERE SHCODE = ''SF-SDCD''')
つまりこれは
UPDATE QTRFIL/SHOHIN SET HSTANK = 28000 WHERE SHCODE = 'SF-SDCD'
を実行することであり商品コード SF-SDCDのレコードの単価: SHTANKを
28000円に更新することを意味している。
このプログラムを実行すると
> call test.com/testsqlc1 1 レコードを更新しました。
のようになり結果をQUERYで確認すると
報告書の表示 報告書の幅 . . . . . 行の位置指定 . . . . . . . 桁移動 . . . . . . . . . 行 ....+....1....+....2....+....3....+....4....+....5....+.... 商品 コード 商品名 単価 品種 コード 000001 NV-BS30S 目次ビデオ 165,000 0002 000002 NV-BS50S ビデオ画王 200,000 0002 000003 NV-CF2 薄型テレビ 98,000 0003 000004 NV-CF81 更新テスト 58,000 0004 000005 NV-CF9 漢字テスト 19,000 0002 000006 NV-F850 音声録画ビデオ 140,000 0002 000007 NV-HK1 歌えるビデオ 90,000 0002 000008 NV-H1T-S みんなのビデオ 69,800 0002 000009 NV-SX10 ビデオ画王 115,000 0002 000010 NV-W1 世界放送方式ビデオ 350,000 0002 000011 RX-DT75 CDラジオカセット 53,800 0003 000012 SC-CH150 超ミニ・コンポ 70,000 0003 000013 SC-CH505 パーソナル・ミニコンポ 100,000 0003 000014 SC-CH655 ロングプレイ・コンポ 129,000 0003 000015 SC-CH950 ドルビー・ミニコンポ 162,000 0003 000016 SF-SDCD FFFFF 28,000 0009
のようにして見事 SF-SDCDの単価は 28000円に更新されている。
( 更新前は 19000円であった)
SQL : UPDATE QTRFIL/SHOHIN SET HSTANK = 28000 WHERE SHCODE = 'SF-SDCD'
を更新したのは次のたった一行のRUNSQLコマンドであった。
RUNSQL SQL(&STR) COMMIT(*NONE)
このようにRUNSQLを使えば SQLで UPDATE/INSERT/DELETE による更新を行うことが
できる。
ただし RUNSQLが使えるのは OS Ver7.1からである。