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からである。
