Migaro. 技術Tips

                       

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


Delphi/400 IBM i のビューを使用したファイル内のフィールド情報取得

IBM i では、QSYS2ライブラリに用意されているビューを参照することで
様々な情報を取得できます。

今回は「SYSCOLUMNS」ビューを使用してファイル内のフィールド情報を取得します。


 

SYSCOLUMNSビューを使用すると、指定したフィールドの情報を桁数やテキストからCCSID・別名に至るまで取得することができます。
公式のヘルプページには以下のように記載されています。

 
SYSCOLUMNSビューには、SQLスキーマの中の各表または各ビューの各列ごとに行が1つずつ入ります。

公式ヘルプページより

 

SYSCOLUMNSビュー内のほとんどの列(フィールド)はDelphi/400でも取得可能です。

例えば列「LABEL」を取得する以下のようなSQLをDelphi/400から発行することで、
ファイル「LIBNAME/FILENAME」のカラムヘディングを取得できます。

※取得結果(LABEL)はそのままだと文字化けするため、CHARでキャストします。

SELECT CHAR(LABEL) AS LBL 

FROM  QSYS2/SYSCOLUMNS
WHERE SYSTEM_TABLE_SCHEMA = 'LIBNAME'
AND   SYSTEM_TABLE_NAME   = 'FILENAME'

 

カラムヘディング以外にもフィールドの様々な情報(詳細は公式ヘルプページ参照)を
取得できるため、以下のようなSQLもDelphi/400から直接実行可能です。

SELECT
NAME      ,             /*長いフィールド名*/
TBNAME    ,             /*長いファイル名*/
TBCREATOR ,             /*TABLE_OWNER*/
COLNO     ,             /*ORDINAL_POSITION*/
COLTYPE   ,             /*DATA_TYPE*/
LENGTH    ,             /*フィールドのSQL長*/
SCALE     ,             /*NUMERIC_SCALE*/
NULLS     ,             /*空値可能:Y-YES,N-NO*/
UPDATES   ,             /*更新可能:Y-YES,N-NO*/
REMARKS   ,             /*詳細フィールド記述*/
DEFAULT   ,             /*省略時の標識:Y-YES,N-NO*/
CHAR(LABEL) AS LBL,     /*フィールド見出し*/
STORAGE   ,             /*バイト数での内部長*/
PRECISION ,             /*NUMERIC_PRECISION*/
CCSID     ,             /*文字フィールドCCSID*/
DBNAME    ,             /*ライブラリー名*/
DFTVALUE  ,             /*フィールドの省略時値*/
CHARLEN   ,             /*文字フィールドの文字数*/
CHARBYTE  ,             /*文字フィールド長*/
RADIX     ,             /*NUMERIC_PRECISION_RADIX*/
DATPRC    ,             /*DATETIME_PRECISION*/
CHAR(LABELTEXT) AS TXT, /*フィールド・テキスト*/
SYS_CNAME ,             /*フィールド名*/
SYS_TNAME ,             /*ファイル名*/
SYS_DNAME ,             /*ライブラリー名*/
TYPESCHEMA,             /*UDT ライブラリー名*/
TYPENAME  ,             /*UDT 長い名前*/
IDENTITY  ,             /*IS_IDENTITY*/
GENERATED ,             /*IDENTITY_GENERATION*/
START     ,             /*IDENTITY_START*/
INCREMENT ,             /*IDENTITY_INCREMENT*/
MINVALUE  ,             /*IDENTITY_MINIMUM*/
MAXVALUE  ,             /*IDENTITY_MAXIMUM*/
CYCLE     ,             /*IDENTITY_CYCLE*/
CACHE     ,             /*IDENTITY_CACHE*/
ORDER     ,             /*IDENTITY_ORDER*/
HIDDEN    ,             /*HIDDEN*/
FLDPROC                 /*HAS_FLDPROC*/

FROM QSYS2/SYSCOLUMNS
WHERE SYSTEM_TABLE_SCHEMA = 'LIBNAME'
AND   SYSTEM_TABLE_NAME   = 'FILENAME'
/*以下はオプション*/
AND   SYSTEM_COLUMN_NAME  = 'FIELDNAME'
ORDER BY COLNO


<※ご留意事項>

  • 「SELECT * FROM ~~」とすると、Delphi/400が対応していない型の列が存在するためエラーになります。
    上記のSQLは、V7R1においてエラーにならない全ての列を取得する場合の例となります。
  • SQL文中の「/*~~*/」で囲まれた部分はコメントになるため、
    上記のSQL文はWHERE句の中身だけ変更すればそのまま実行して頂けます。

    (コメント中の「半角コロン」はパラメータと認識されるため、全角コロンに置き換えて下さい。)
  • 取得結果の件数が膨大になりフリーズすることを避けるため、通常はライブラリ名およびファイル名の絞り込みは必ず行って下さい。
  • WHERE句で「SYSTEM_COLUMN_NAME」も指定すると、フィールド名で絞り込むこともできます。
    ライブラリ名およびファイル名を指定せずにSYSTEM_COLUMN_NAMEだけで絞り込むと、
    同名のフィールドがどのライブラリ・ファイルに存在するか探すことも可能です。
  • 取得結果は順不同になるため、SQLの末尾に「ORDER BY COLNO」を付加するとフィールドを順番に表示できます。

 

下図は上記のSQLを使って「QSYS2/SYSCOLUMNS」自身の情報を取得した結果のサンプルです。
1フィールドの情報が1レコードとして表示されます。

 


 

このロジックを使用することで、
Delphi/400のTFDQueryでファイルを開いた後にTDBGridに表示させたい場合、
タイトル部を予め設定しておかなくても以下のようにコーディングすることで
取得したフィールドのテキストを自動セットできるようになります。

(DSPFFDコマンドを使用する方法もありますが、この方法ならワークファイル不要な上にSQLのみで完結できます。)

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  // 元データの取得部分(ここで使用している「CO422/CUSTOMER」はDelphi/400付属のサンプルファイル)
  FDQuery1.Close;
  FDQuery1.SQL.Text := ' SELECT * FROM CO422/CUSTOMER ';
  FDQuery1.Open;

  // フィールド・テキストの取得
  FDQuery2.Close;
  FDQuery2.SQL.Text := ' SELECT SYS_CNAME, CHAR(LABEL) AS LBL, CHAR(LABELTEXT) AS TXT ' +
                       ' FROM QSYS2/SYSCOLUMNS ' +
                       ' WHERE SYSTEM_TABLE_SCHEMA = ''CO422'' ' +    // ※ファイルのライブラリ名
                       ' AND   SYSTEM_TABLE_NAME   = ''CUSTOMER'' ';  // ※ファイル名
  FDQuery2.Open;

  // 取得した順に、フィールドのテキストをグリッドに貼り付け
  for i := 0 to DBGrid1.FieldCount - 1 do
  begin
    if (FDQuery2.Locate('SYS_CNAME', DBGrid1.Fields[i].FieldName)) then
    begin
      // テキストをセット
      if (FDQuery2.FieldByName('TXT').AsString <> '') then
      begin
        DBGrid1.Columns.Items[i].Title.Caption := FDQuery2.FieldByName('TXT').AsString;
      end

      // テキストが空の場合、代わりにCOLHDGをセット
      else
      begin
        DBGrid1.Columns.Items[i].Title.Caption := FDQuery2.FieldByName('LBL').AsString;
      end;
    end;
  end;
  FDQuery2.Close;
end;
上記のロジックでDBGridのタイトル部にテキストをセットした例