Migaro. 技術Tips

                       

ミガロ. 製品の技術情報
IBMiの活用に役立つ情報を掲載!


SmartPad4i  RPGでSQLを使用する方法

SmartPad4i(Cobos4i)は、インターフェースをHTMLで作成してバックエンド側のロジックをIBMiプログラム(RPG,COBOL)で作成できる開発ツールです。RPG、RPGLEだけでなくSQLRPGLEでバックエンド側のプログラムを作成することもできます。簡単なSQL実行方法と、RPGプログラムでは作成するのが困難な正規表現チェックについて、SQLスカラー関数で実現する方法をご紹介します。

Designer配布後 タイプをSQLRPGLEに変更

SmartPad4i(Cobos4i)はSQLRPGLEでの配布設定はありませんが、RPGLEで配布後にタイプの属性をRPGLEからSQLRPGLEに変更することで、SQLRPGLEとしてプログラムを実行することが可能です。

SQLの記述例

RPGLEではF仕様書でファイルを定義して、C仕様書でファイルを読み込み処理を記述します。
SmartPad4i(Cobos4i)では、固定長のRPGLE(RPG)を使用してロジックを作成可能です。
しかし、SQLを使用すると固定長の記述よりも簡単にデータを取得できる場合もあります。

SQLRPGLEでは、EXEC SQLによる静的SQLの実行や、EXECUTE IMMEDIATEによる動的SQLの実行、カーソルを使用して複数レコード結果を逐次処理することが可能です。

静的SQLの例

静的SQLはプログラム中に記述されたSQLを実行する方法です。
INTOを使用してフィールドに値を設定することができます。

     C/EXEC SQL
     C+     SELECT BUKCOD, BUKNAM
     C+     INTO : OFLD01 ,:OFLD02
     C+     FROM BUKEPF
     C+     ORDER BY BUKCOD
     C/END-EXEC

動的SQLの例

動的SQLはSQL文を文字列として作成後に実行する方法です。
プログラム中でSQLを作成して実行することができます。
 ※例ではSQLインジェクションの考慮をしていません。

     D @SQL            S            100    DIM(1) CTDATA
~ 省略 ~
     C     @SQL(1)       CAT       '''BK0020''':0STMT
     C/EXEC SQL
     C+     EXECUTE IMMEDIATE :STMT
     C/END-EXEC
~ 省略 ~
** @SQL
DELETE FROM BUKEPF WHERE BUKCOD = 

動的にSQLを実行する場合にはPrepareステートメントを使用してパラメータ実行する方法をお勧めします。

     D @SQL            S            100    DIM(1) CTDATA
~ 省略 ~
     C                   MOVEL(P)  @SQL(1)       STMT
     C                   MOVEL(P)  'BK0020'      DLBUKNCD
     C/EXEC SQL
     C+     PREPARE S1 FROM :STMT
     C/END-EXEC
     C/EXEC SQL
     C+     EXECUTE S1 USING :DLBUKNCD
     C/END-EXEC
~ 省略 ~
** @SQL
DELETE FROM BUKEPF WHERE BUKCOD = ?

Cursorを使用する例

カーソルを使用するとレコードを順次取得して処理が可能です。

     C/EXEC SQL
     C+     DECLARE C_BUKE CURSOR FOR
     C+     SELECT BUKCOD, BUKNAM
     C+     FROM BUKEPF
     C+     ORDER BY BUKCOD
     C+     FOR READ ONLY
     C/END-EXEC
     C/EXEC SQL
     C+     OPEN C_BUKE
     C/END-EXEC
     C                   DO        *HIVAL
     C     IDX           IFGT      9999
     C                   LEAVE
     C                   ENDIF
     C     IDX           OCCUR     SOOF02
     C/EXEC SQL
     C+     FETCH NEXT FROM C_BUKE INTO :OFLD01, :OFLD02 :IND_BUKN
     C/END-EXEC
     C     SQLCOD        IFEQ      100
     C                   LEAVE
     C                   ENDIF
     C     SQLCOD        IFLT      0
     C                   LEAVE
     C                   ENDIF
     C     IND_BUKN      IFLT      0
     C                   CLEAR                   OFLD02
     C                   ENDIF
     C                   ADD       1             IDX
     C                   ENDDO
     C/EXEC SQL
     C+     CLOSE C_BUKE
     C/END-EXEC

SQLで正規表現チェック

RPGLEでは正規表現の関数が存在しないため、文字列の中から特定のパターン(規則)をチェックする機能を作成するのが困難です。IBMiのDB2には、SQLスカラー関数で正規表現を扱う機能があるためSQL上で正規表現によるチェックを行うことができます。

SQLRPGLEを使用すると、SQLスカラー関数の機能を使用できるため正規表現以外にも、日付計算やあいまい検索等、RPGLEのプログラムでは作成に時間が必要となる機能も簡単に実装できます。

例えば、正規表現のパターンでメールアドレスをチェックする場合、以下のようなプログラムでチェックが可能です。

例) REGEXEM.SQLRPGLE

**free
  //------------------------------------------------------------------
  //   プログラム名 : REGEXEM
  //   概要         : メールアドレス形式チェック(形式のみ)
  //   判定式       : ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+[.][A-Za-z]{2,}$
  //   使用関数     : REGEXP_COUNT
  //------------------------------------------------------------------
  ctl-opt dftactgrp(*no) actgrp(*new) option(*srcstmt:*nounref);

  dcl-pi *n;
    pEmail    char(254);
    pResult    char(1);
  end-pi;

  if pEmail = *blank;
    pResult = '0';
  else;
    pResult = IsEmailFormat(pEmail);
  endif;
  *inlr = *on;
  //------------------------------------------------------------------
  //   メールアドレス形式チェック関数
  //------------------------------------------------------------------
  dcl-proc IsEmailFormat;
    dcl-pi *n  char(1);
      pEmail   char(254) const;
    end-pi;

    dcl-s pattern varchar(100) ccsid(1208)
       inz('^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+[.][A-Za-z]{2,}$');

    dcl-s matchCnt int(10);

    // 空文字は不正
    if %len(%trim(pEmail)) = 0;
       return '0';
    endif;

    exec sql
      values(REGEXP_COUNT(RTRIM(:pEmail), :pattern))
        into :matchCnt;
    // 正しいEmail
    if matchCnt = 1;
       return '1';
    else;
       return '0';
    endif;
  end-proc;

REGEXP_COUNTは、第一引数のソース文字内で第2引数の正規表現パターンが一致した回数のカウントを戻す機能です。

◆REGEXP_COUNTスカラー関数
https://www.ibm.com/docs/ja/db2/11.1.0?topic=functions-regexp-count

SmartPad4i(Cobos4i)のRPGLEプログラムから呼び出す場合の例です。
‘1’が返却されると正しい形式のEmailアドレスとなります。

     D @ERRMSG         S             50    DIM(1) CTDATA
~ 省略 ~
C010  * <YOURCODE>
--->  * YOUR CODE
     C     PL010         PLIST
     C                   PARM                    PEMAIL          254
     C                   PARM                    PRESLT            1
C010  * </YOURCODE>
~ 省略 ~
     C     SPACTN        IFEQ      'A1'
     C                   MOVEL(P)  IINP01        PEMAIL
     C                   MOVEL(P)  '0'           PRESLT
     C                   CALL      'REGEXEM'     PL010
     C*
     C     PRESLT        IFEQ      '0'
     C                   MOVEL(P)  @ERRMSG(1)    OERR01
     C                   ELSE
     C                   MOVEL(P)  *BLANK        OERR01
     C                   ENDIF
     C                   ENDIF
~ 省略 ~
** @ERRMSG
メールアドレスが正しくありません。