メニューボタン
IBMi海外記事2019.09.12

%SCANで事足りないときには

Ted Holt 著

RPGの%SCAN組み込み関数は素晴らしい関数です。System/36でRPG IIを使用していて、文字列内で文字列を探さなければならなかったときのことを今でも覚えています。それは、どれほどつらい苦行だったことでしょう。とは言うものの、状況によっては、%SCANに行ってもらう必要があるすべてのことを%SCANが行えるわけではありません。そうしたケースでは、SQLの力を頼りにします。

SQLが便利な1つのケースは、大文字小文字の区別をしないスキャンが必要なケースです。以下のように、RPGの%SCAN関数の代わりに、SQLのLOCATEおよびUPPER関数を使用します。

dcl-s  Description  char(48);
dcl-s  pos          int (10);

exec sql
   set :pos = locate ('HAMMER', upper(:Description));

Descriptionの値がClaw hammer 16ozである場合、posの値は6になります。

似ているSQL関数が2つあります(POSITIONおよびPOSSTR)。詳細は、それぞれのリンクから参照してください。

もうひとつのケースは、ワイルドカード スキャンの場合です。そのようなケースでは、SQLのLIKE述語を使用することができます。

dcl-s  Description  char(48);
dcl-s  Matched      char( 1);

exec sql
   set :Matched = case
      when :Description like '%16%oz%hammer%'
         then '1' else '0' end;

このコードは、Descriptionが16オンスのハンマー(16-ounce hammer)を参照しているかどうかを判定します。Descriptionが以下の値の場合に、Matchedが1にセットされることになります。

  • 16oz claw hammer(16オンスのクロー ハンマー)
  • 16-oz. claw hammer(16オンスのクロー ハンマー)
  • 16 oz claw hammer(16オンスのクロー ハンマー)
  • Famousbrand 16 oz claw hammer(有名ブランドの16オンスのクロー ハンマー)
  • 16 oz bricklayers hammer(16オンスのレンガ用ハンマー)

また、正規表現をスキャンすることもできます。その場合は、REGEXP_LIKE述語を使用します。

dcl-s  Description  char(48);
dcl-s  Matched      char( 1);

exec sql
   set :Matched = case
      when regexp_like (:Description, '16.*oz.*(hammer|mallet)')
         then '1' else '0' end;

このコードは、Descriptionが16オンスのハンマーまたはマレット(木槌)(16-ounce hammer or mallet)を参照しているかどうかを判定します。前の例で示した値の場合、いずれもMatchedが1にセットされることになります。さらに次の2つの場合にも、Matchedが1にセットされることになります。

  • 16oz rubber mallet(16オンスのゴム製の槌)
  • Famousbrand 16 oz mallet(有名ブランドの16オンスの木槌)

スキャンで大文字小文字を区別しないようにする場合は、REGEXP_LIKEの3番目のパラメーターにiを指定します。

dcl-s  Description  char(48);
dcl-s  Matched      char( 1);

exec sql
   set :Matched = case
      when regexp_like (:Description, '16.*oz.*(hammer|mallet)', 'i')
         then '1' else '0' end;

次の例は、REGEXP_LIKE述語に代わって、REGEXP_INSTR関数を使用する例です。

dcl-s  Description  char(48);                                     
dcl-s  pos          int (10);                                     
                                                                  
exec sql                                                          
   set :pos =                                                     
           regexp_instr (:Description, '16.*oz.*(hammer|mallet)');

DescriptionがFamousbrand 16oz claw hammerである場合、posは13となります。

%SCANのような素晴らしい関数をRPGで利用できるようにするために、IBMが行ってくれたすべてのことに対して、私は心の底から感謝します。また、IBMがRPGプログラムでSQLを利用可能にしてくれたことについても、心の底から感謝しています。おかげで、こんなに快適になりました。

あわせて読みたい記事

PAGE TOP