Adabas データベースのデータへのアクセス

このドキュメントでは、Natural を使用して Adabas データベースのデータにアクセスするときのさまざまな面について説明します。

以下のトピックについて説明します。


Adabas データベース管理インターフェイス ADA および ADA2

ADA と SQL が異なるインターフェイスであるのと同様に、Natural の Adabas データベース管理インターフェイス ADA と ADA2 は異なるインターフェイスとみなされます。

データベースタイプ ADA は、Natural の Adabas データベースに対するデフォルトインターフェイスです。Open Systems の Adabas バージョン 6 およびメインフレームの Adabas バージョン 8 に導入された新しい Adabas 機能の影響がない場合に適しています。

データベースタイプ ADA2 は、Open Systems のバージョン 6 以降およびメインフレームのバージョン 8 以降の Adabas データベースに対する拡張インターフェイスとして用意されています。このデータベースタイプでは、特に、Adabas LA フィールド、Adabas ラージオブジェクトフィールド、および拡張 Adabas バッファ長がサポートされています。Adabas LA フィールドおよびラージオブジェクトフィールドがサポートされるということは、ビューの定義で Natural 形式 (A) DYNAMIC が使用されることを意味しています。また、拡張 Adabas バッファ長のサポートにより、サイズが 64 KB を超えるビューを定義できます。詳細については、「データベースビューの定義」を参照してください。

データベースタイプ ADA2 はマルチフェッチ処理をサポートしません。対応するグローバル定義やローカル定義は、ランタイム時に無視されます。

専用のシステムファイルを持つ Software AG 製品には、データベースタイプが ADA の対応する物理データベースが必要です。

データベースタイプ ADA でコンパイルされた Natural オブジェクトは、対応する Adabas データベースがデータベースタイプ ADA2 で定義されている環境で実行できます。

データ定義モジュール - DDM

Natural がデータベースファイルにアクセスできるようにするには、物理データベースファイルの論理定義が必要です。このような論理ファイル定義は、データ定義モジュール(DDM)と呼ばれます。

このセクションでは、次のトピックについて説明します。

データ定義モジュールの使用

データ定義モジュールには、ファイルの個々のフィールドについての情報が含まれています。この情報は、Natural プログラムでこれらのフィールドを使用するために必要です。DDM は、物理データベースファイルの論理ビューを構成しています。

データベースの各物理ファイルに、1 つ以上の DDM を定義できます。各 DDM について、DEFINE DATA ステートメントドキュメントの「ビューの定義」での説明、および「データベースビューの定義」の説明に従って、1 つまたは複数のデータビューを定義できます。

DDM は、Natural 管理者が Predict(Predict を使用できない場合は、対応する Natural 機能)を使用して定義します。

DDM の管理

システムコマンド SYSDDM を使用して、SYSDDM ユーティリティを呼び出します。SYSDDM ユーティリティを使用すると、Natural のデータ定義モジュールの作成および管理に必要なすべての機能を実行できます。

SYSDDM ユーティリティの詳細については、『エディタ』ドキュメントの「DDM サービス」を参照してください。

各データベースフィールドについて、DDM にはデータベース内部のフィールド名の他に、Natural プログラムで使用されるフィールドの名前である "外部" フィールド名も含まれています。また、フィールドのフォーマットと長さ、およびフィールドが DISPLAY または WRITE ステートメントで出力されるときに使われる各種の指定(列見出し、編集マスクなど)も DDM に定義されます。

DDM に定義されるフィールド属性については、『エディタ』ドキュメントの「DDM サービス」セクションの「DDM エディタの使用」を参照してください。

DDM のリスト/表示

データベース配列

Adabas は、マルチプルバリューフィールドおよびピリオディックグループの形で、データベース内の配列構造をサポートします。

このセクションでは、次のトピックについて説明します。

マルチプルバリューフィールド

マルチプルバリューフィールドは、任意のレコード内に複数の値を持つことができるフィールドです。値の数は 65534 以下ですが、Adabas バージョンおよび FDT の定義に応じて異なります。

例:

上記の図を EMPLOYEES ファイルのレコードと仮定すると、最初のフィールド(Name)はエレメンタリフィールドであり、1 つの値、つまり従業員の名前のみを含めることができます。これに対して 2 つ目のフィールド(Languages)には、従業員が話す言語が含まれています。従業員は複数の言語を話せる可能性があるので、マルチプルバリューフィールドになっています。

ピリオディックグループ

ピリオディックグループは、任意のレコード内で複数のオカレンスを持つことができるエレメンタリフィールドまたはマルチプルバリューフィールドのグループです。オカレンスの数は 65534 以下ですが、Adabas バージョンおよびフィールド定義テーブル(FDT)の定義に応じて異なります。

マルチプルバリューフィールドに含まれる各値は、一般に "オカレンス" と呼ばれます。オカレンスの数は、フィールドに含まれる値の数であり、特定のオカレンスは特定の値を表します。同様に、ピリオディックグループでは、オカレンスは複数の値の集まりを表します。

例:

上の図が車両ファイル内のレコードであると仮定すると、最初のフィールド(Name)は人物の名前を含むエレメンタリフィールドです。「Cars」は、その人物が所有する自動車を含むピリオディックグループです。ピリオディックグループは、各自動車の登録番号、メーカー、およびモデルの 3 つのフィールドで構成されています。Cars の各オカレンスには 1 台の車に関する値が含まれます。

マルチプルバリューフィールドとピリオディックグループの参照

マルチプルバリューフィールドまたはピリオディックグループの 1 つ以上のオカレンスを参照するには、フィールド名の後に "インデックス表記" を指定します。

例:

次の例では、上述の例のマルチプルバリューフィールド LANGUAGES とピリオディックグループ CARS を使用します。

マルチプルバリューフィールド LANGUAGES の各値は、次のように参照できます。

説明
LANGUAGES (1) 最初の値(SPANISH)を参照します。
LANGUAGES (X) 変数 X の値によって、参照する値が決まります。
LANGUAGES (1:3) 最初の 3 つの値(SPANISHCATALAN、および FRENCH)を参照します。
LANGUAGES (6:10) 6 番目から 10 番目の値を参照します。
LANGUAGES (X:Y) 変数 X と変数 Y の値によって、参照する値が決まります。

ピリオディックグループ CARS のさまざまなオカレンスも同様の方法で参照できます。

説明
CARS (1) 最初のオカレンス(B-123ABC/SEAT/IBIZA)を参照します。
CARS (X) 変数 X の値によって、参照するオカレンスが決まります。
CARS (1:2) 最初の 2 つのオカレンス(B-123ABC/SEAT/IBIZA および B-999XYZ/VW/GOLF)を参照します。
CARS (4:7) 4 番目から 7 番目のオカレンスを参照します。
CARS (X:Y) 変数 X と変数 Y の値によって、参照するオカレンスが決まります。

ピリオディックグループ内のマルチプルバリューフィールド

Adabas 配列には、2 次元まで、つまり 1 つのピリオディックグループ内に 1 つのマルチプルバリューフィールドを含めることができます。

例:

上の図が車両ファイル内のレコードであると仮定すると、最初のフィールド(Name)は人物の名前を含むエレメンタリフィールドです。「Cars」は、その人物が所有する自動車を含むピリオディックグループです。このピリオディックグループは、各自動車の登録番号、サービス日付、およびメーカーの 3 つのフィールドで構成されています。ピリオディックグループ Cars 内のフィールド Servicing はマルチプルバリューフィールドであり、各車の異なるサービス日付が含まれています。

ピリオディックグループ内のマルチプルバリューフィールドの参照

ピリオディックグループ内のマルチプルバリューフィールドの 1 つ以上のオカレンスを参照するには、フィールド名の後に "インデックス表記" を指定します。

例:

次の例では、上述の例のピリオディックグループ CARS 内のマルチプルバリューフィールド SERVICING を使用します。マルチプルバリューフィールドの各値は、次のように参照できます。

説明
SERVICING (1,1) CARS の最初のオカレンスにある SERVICING の最初の値(31-05-97)を参照します。
SERVICING (1:5,1) CARS の最初の 5 つのオカレンスにある SERVICING の最初の値を参照します。
SERVICING (1:5,1:10) CARS の最初の 5 つのオカレンスにある SERVICING の最初の 10 個の値を参照します。

データベース配列の内部カウントの参照

レコードに値またはオカレンスがいくつ存在するかが不明なマルチプルバリューフィールドやピリオディックグループの参照が必要になることがあります。Adabas では、各マルチプルバリューフィールドの値の数、および各ピリオディックグループのオカレンスの数の内部カウントが保持されています。このカウントは、READ ステートメントでフィールド名の直前に C* を指定することによって読み込むことができます。

カウントは、フォーマット/長さ N3 で返されます。詳細については、「データベース配列の内部カウントの参照」を参照してください。

説明
C*LANGUAGES マルチプルバリューフィールド LANGUAGES の値の数を返します。
C*CARS ピリオディックグループ CARS のオカレンスの数を返します。
C*SERVICING (1) ピリオディックグループの最初のオカレンスにあるマルチプルバリューフィールド SERVICING の値の数を返します。SERVICING はピリオディックグループ内のマルチプルバリューフィールドであると仮定しています。

データベースビューの定義

Natural プログラムでデータベースフィールドを使用できるようにするには、データベースビューでフィールドを指定する必要があります。

ビューでは、フィールドを取得する、データ定義モジュールの名前(「データ定義モジュール - DDM」を参照)、およびデータベースフィールドの名前自体(「フィールド定義」を参照)、(つまり、データベース内部のショートネームではなく、ロングネーム)を指定します。

ビューは DDM 全体を含めたり、そのサブセットのみを含めたりすることができます。ビューのフィールドの順番を、基礎となる DDM と同じにする必要はありません。

データベースアクセスのためのステートメント」セクションで説明されているように、どのデータベースにアクセスするかを決定するために、ビュー名が READFINDHISTOGRAM ステートメントで使用されます。

ビュー定義オプションの完全な構文、またはフィールドのグループの定義/再定義の詳細については、『ステートメント』ドキュメントにある DEFINE DATA ステートメントの説明の「ビューの定義」を参照してください。

基本的に、データベースビューを定義する場合、次のオプションがあります。

  • プログラム内部
    プログラム内部、つまりプログラムの DEFINE DATA ステートメント内で直接データベースビューを定義できます。

  • プログラム外部
    プログラム外部で、つまり別のオブジェクト(そのデータエリアを参照するプログラムの DEFINE DATA ステートメントにより、ローカルデータエリア(LDA)またはグローバルデータエリア(GDA)のいずれか)にデータベースビューを定義できます。

Start of instruction setプログラム内部でデータベースビューを定義するには

  1. レベル 1 では、ビュー名を次のように指定します。

    1 view-name VIEW OF ddm-name

    view-name はビューに選択した名前、ddm-name はビューに指定されたフィールドの取得元となる DDM の名前です。

  2. レベル 2 では、DDM のデータベースフィールドの名前を指定します。

    次の図に示すように、ビューの名前は ABC で、DDM XYZ から取得したフィールド NAMEFIRST-NAME、および PERSONNEL-ID で構成されています。

    このビューでは、データベースフィールドのフォーマットと長さは、基礎となる DDM ですでに定義されているため、指定する必要はありません。

    サンプルプログラム:

    この例では、view-nameVIEWEMP で、ddm-nameEMPLOYEESです。DDM から取得したデータベースフィールドの名前は、NAMEFIRST-NAME および PERSONNEL-ID です。

    DEFINE DATA LOCAL 
    1 VIEWEMP VIEW OF EMPLOYEES 
      2 NAME 
      2 FIRST-NAME 
      2 PERSONNEL-ID 
    1 #VARI-A (A20) 
    1 #VARI-B (N3.2) 
    1 #VARI-C (I4) 
    END-DEFINE 
    ...

Start of instruction setプログラム外部でデータベースビューを定義するには

  1. プログラムで、次のように指定します。

    DEFINE DATA LOCAL 
           USING <data-area-name> 
    END-DEFINE 
      ...

    ここで、data-area-name は、ローカルまたはグローバルデータエリアに選択する名前です(LDA39 など)。

  2. 参照するデータエリアで、次のように指定します。

    1. Name 列のレベル 1 でビューに選択した名前を指定し、Miscellaneous 列では、ビューに指定されたフィールドの取得元となる DDM の名前を指定します。

    2. レベル 2 では、DDM のデータベースフィールドの名前を指定します。

      LDA39

      この例では、ビュー名は VIEWEMP で、DDM 名は EMPLOYEESです。DDM から取得したデータベースフィールドの名前は、PERSONNEL-IDFIRST-NAME および NAME です。

      I T L  Name                             F Length     Miscellaneous             
      All -- -------------------------------- - ---------- ------------------------->
        V  1 VIEWEMP                                       EMPLOYEES                 
           2 PERSONNEL-ID                     A          8                           
           2 FIRST-NAME                       A         20                           
           2 NAME                             A         20                           
           1 #VARI-A                          A         20                           
           1 #VARI-B                          N        3.2                           
           1 #VARI-C                          I          4                          

タイプ ADA2 のデータベースに関する考慮事項

コンフィグレーションユーティリティの DBMS 割り当てテーブル(『コンフィグレーションユーティリティ』ドキュメントの「データベース管理システムの割り当て」を参照)に指定されているタイプ ADA2 のデータベースでは、次のことが該当します。

  • Adabas LA/LB オプションである大きな英数字(LA)またはラージオブジェクト(LOB)のフィールドを使用する場合は、A20U20 などの固定フォーマット/長さ、および (A)DYNAMICU(DYNAMIC) などのダイナミックフォーマット/長さの両方を使用して、ビュー定義内にフィールドを指定できます。

  • LA フィールドまたは LOB フィールドに関係のある長さインジケータフィールド L@... も、ビュー内に指定できます。

データベースアクセスのステートメント

データベースからデータを読み込むには、次のステートメントを使用できます。

ステートメント 意味
READ 指定した順番でデータベースからレコードの範囲を選択します。
FIND 指定した検索条件に一致するレコードをデータベースから選択します。
HISTOGRAM 1 つのデータベースフィールドの値のみを読み込みます。または、指定した検索条件に一致するレコードの数を決定します。

READ ステートメント

以下のトピックについて説明します。

READ ステートメントの使用

READ ステートメントは、データベースからレコードを読み取るために使用します。レコードがデータベースから読まれる順番は次のとおりです。

このドキュメントでは、READ IN LOGICAL SEQUENCE のみを取り上げます。これは最も頻繁に使用される形の READ ステートメントです。

他の 2 つのオプションの詳細については、『ステートメント』ドキュメントの READ ステートメントの説明を参照してください。

READ ステートメントの基本構文

READ ステートメントの基本構文は次のとおりです。

READview IN LOGICAL SEQUENCE BY descriptor

または、以下のように短くすることができます。

READview LOGICAL BYdescriptor

各項目の意味を次に示します。

view DEFINE DATA ステートメントで定義され、「データベースビューの定義」で説明されるビューの名前。
descriptor そのビューで定義されるデータベースフィールドの名前。このフィールドの値によって、データベースから読み込まれるレコードの順番が決まります。

ディスクリプタを指定する場合は、キーワード LOGICAL を指定する必要はありません。

READview BYdescriptor

ディスクリプタを指定しない場合は、DDMDefault Sequence にデフォルトディスクリプタとして定義されたフィールドの値の順番でレコードが読み込まれます。ただし、ディスクリプタを指定しない場合は、次のようにキーワード LOGICAL を指定する必要があります。

READview LOGICAL

READ ステートメントの例

** Example 'READX01': READ
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 PERSONNEL-ID
  2 JOB-TITLE
END-DEFINE
*
READ (6) MYVIEW BY NAME
  DISPLAY NAME PERSONNEL-ID JOB-TITLE
END-READ
END

プログラム READX01 の出力:

上記の例の READ ステートメントでは、EMPLOYEES ファイルのレコードが各従業員の姓のアルファベット順に読み込まれます。

プログラムによって次のような出力が作成され、各従業員の情報がそれぞれの姓のアルファベット順に表示されます。

Page      1                                                  04-11-11  14:15:54
                                                                                 
        NAME         PERSONNEL          CURRENT                                
                        ID             POSITION                                
-------------------- --------- -------------------------                       
                                                                                 
ABELLAN              60008339  MAQUINISTA                                      
ACHIESON             30000231  DATA BASE ADMINISTRATOR                         
ADAM                 50005800  CHEF DE SERVICE                                 
ADKINSON             20008800  PROGRAMMER                                      
ADKINSON             20009800  DBA                                             
ADKINSON             2001100

従業員を生年月日順にリストするレポートを作成するためにレコードを読み込む場合の適切な READ ステートメントは次のようになります。

READ MYVIEW BY BIRTH

指定できるのは、基礎となる DDM で "ディスクリプタ" として定義されているフィールドのみです。サブディスクリプタ、スーパーディスクリプタ、ハイパーディスクリプタ、フォネティックディスクリプタ、またはノンディスクリプタの場合もあります。

読み込むレコード数の制限

上記のプログラム例で示されているように、キーワード READ の後にカッコで囲んだ数字を次のように指定することによって、読み込まれるレコード数を制限できます。

READ (6) MYVIEW BY NAME

上記の例では、READ ステートメントで 6 件を超えるレコードは読み込まれなくなります。

リミット表記がない場合、上記の READ ステートメントによって、EMPLOYEES ファイルのすべてのレコードが姓の順に A から Z まで読み込まれます。

STARTING/ENDING 節

READ ステートメントでは、ディスクリプタフィールドのに基づいてレコードの選択を限定することもできます。BY 節で EQUAL TO/STARTING FROM オプションを設定することによって、読み込みを開始する値を指定できます。(キーワード BY を使用する代わりに、キーワード WITH を指定できます。このキーワードには、同じ効果があります)。THRU/ENDING AT オプションを追加して、読み込みを終了する値を論理順で指定することもできます。

例えば、TRAINEE で開始して Z まで継続する職種の順番で従業員をリストするには、次のいずれかのステートメントを使用します。

READ MYVIEW WITH JOB-TITLE = 'TRAINEE' 
READ MYVIEW WITH JOB-TITLE STARTING FROM 'TRAINEE' 
READ MYVIEW BY JOB-TITLE = 'TRAINEE' 
READ MYVIEW BY JOB-TITLE STARTING FROM 'TRAINEE'

等号(=)または STARTING FROM オプションの右側の値はアポストロフィで囲む必要があります。値が数値の場合は、このテキスト表記は不要です。

読み込む一連のレコードは、THRU/ENDING AT 節で終了制限を追加することによって、より厳密に指定できます。

職種が TRAINEE のレコードだけを読み込むには、次のように指定します。

READ MYVIEW BY JOB-TITLE STARTING FROM 'TRAINEE' THRU 'TRAINEE'
READ MYVIEW WITH JOB-TITLE EQUAL TO 'TRAINEE' 
                           ENDING AT 'TRAINEE'

職種が A または B で始まるレコードだけを読み込むには、次のように指定します。

READ MYVIEW BY JOB-TITLE = 'A' THRU 'C' 
READ MYVIEW WITH JOB-TITLE STARTING FROM 'A' ENDING AT 'C'

値は、THRU/ENDING AT の後に指定された値まで、その値を含めて読み込まれます。上記の 2 つの例では、職種が A または B で始まる全レコードが読み込まれます。職種 C があれば、これも読み込まれますが、次に高い値である CA は読み込まれません。

WHERE 節

WHERE 節を使用して、読み込むレコードをさらに限定することができます。

例えば、米国通貨で給与が支払われ、職種が TRAINEE で始まる従業員のみを必要とする場合は、次のように指定します。

READ MYVIEW WITH JOB-TITLE = 'TRAINEE'
            WHERE CURR-CODE = 'USD'

WHERE 節は、次のように BY 節とともに使用することもできます。

READ MYVIEW BY NAME  
            WHERE SALARY = 20000

WHERE 節は、次の 2 つの点で BY 節と異なります。

  • WHERE 節に指定するフィールドがディスクリプタである必要はありません。

  • WHERE オプションに続く式は論理条件です。

WHERE 節では次の論理演算子が有効です。

EQUAL EQ =
NOT EQUAL TO NE ¬=
LESS THAN LT <
LESS THAN OR EQUAL TO LE <=
GREATER THAN GT >
GREATER THAN OR EQUAL TO GE >=

以下のプログラムは、STARTING FROMENDING AT および WHERE 節の使用方法を示しています。

** Example 'READX02': READ  (with STARTING, ENDING and WHERE clause)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 JOB-TITLE
  2 INCOME     (1:2)
    3 CURR-CODE
    3 SALARY
    3 BONUS    (1:1)
END-DEFINE
*
READ (3) MYVIEW WITH  JOB-TITLE
STARTING FROM 'TRAINEE' ENDING AT 'TRAINEE'
                WHERE CURR-CODE (*) = 'USD'
  DISPLAY NOTITLE NAME / JOB-TITLE 5X INCOME (1:2)
  SKIP 1
END-READ
END

プログラム READX02 の出力:

         NAME                            INCOME
         CURRENT
        POSITION              CURRENCY   ANNUAL     BONUS
                                CODE     SALARY
-------------------------     -------- ---------- ----------
 
SENKO                         USD           23000          0
TRAINEE                       USD           21800          0
 
BANGART                       USD           25000          0
TRAINEE                       USD           23000          0
 
LINCOLN                       USD           24000          0
TRAINEE                       USD           22000          0

READ ステートメントのその他の例

次の例のプログラムを参照してください。

FIND ステートメント

以下のトピックについて説明します。

FIND ステートメントの使用

FIND ステートメントは、指定した検索条件に一致するレコードをデータベースから選択するために使用します。

FIND ステートメントの基本構文

FIND ステートメントの基本構文は次のとおりです。

FIND RECORDS INview WITHfield = value

または、以下のように短くすることができます。

FINDview WITHfield = value

各項目の意味を次に示します。

view DEFINE DATA ステートメントで定義され、「データベースビューの定義」で説明されるビューの名前。
field そのビューで定義されるデータベースフィールドの名前。

field に指定できるのは、基礎となる DDM で "ディスクリプタ" として定義されているフィールドのみです。サブディスクリプタ、スーパーディスクリプタ、ハイパーディスクリプタ、またはフォネティックディスクリプタの場合もあります。

完全な構文については、FIND ステートメントのドキュメントを参照してください。

処理するレコード数の制限

上述した READ ステートメントの場合と同様に、キーワード FIND の後にカッコで囲んだ数字を指定することによって、処理するレコード数を制限できます。

FIND (6) RECORDS IN MYVIEW WITH NAME = 'CLEGG'

上記の例では、検索条件に一致する最初の 6 つのレコードだけが処理されます。

リミット表記がない場合は、検索条件に一致するすべてのレコードが処理されます。

注意:
FIND ステートメントに WHERE 節(下記参照)が含まれている場合、WHERE 節の結果として拒否されるレコードは制限に対してカウントされません

WHERE 節

FIND ステートメントの WHERE 節を使用すると、WITH 節で選択したレコードが読み込まれた、このレコードの処理が実行されるに評価される追加の選択条件を指定できます。

WHERE 節が含まれる FIND ステートメントの例

** Example 'FINDX01': FIND (with WHERE)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 PERSONNEL-ID
  2 NAME
  2 JOB-TITLE
  2 CITY
END-DEFINE
*
FIND MYVIEW WITH CITY = 'PARIS'
            WHERE JOB-TITLE = 'INGENIEUR COMMERCIAL'
  DISPLAY NOTITLE CITY JOB-TITLE PERSONNEL-ID NAME
END-FIND
END

注意:
この例では、WITH WHERE 節の両方の条件に一致するレコードだけが DISPLAY ステートメントで処理されます。

プログラム FINDX01 の出力:

        CITY                  CURRENT          PERSONNEL         NAME
                             POSITION             ID
-------------------- ------------------------- --------- --------------------
 
PARIS                INGENIEUR COMMERCIAL      50007300  CAHN
PARIS                INGENIEUR COMMERCIAL      50006500  MAZUY
PARIS                INGENIEUR COMMERCIAL      50004700  FAURIE
PARIS                INGENIEUR COMMERCIAL      50004400  VALLY
PARIS                INGENIEUR COMMERCIAL      50002800  BRETON
PARIS                INGENIEUR COMMERCIAL      50001000  GIGLEUX
PARIS                INGENIEUR COMMERCIAL      50000400  KORAB-BRZOZOWSKI

IF NO RECORDS FOUND 条件

WITH 節と WHERE 節に指定した検索条件に一致するレコードが見つからない場合、FIND 処理ループ内のステートメントは実行されません。上記の例では、DISPLAY ステートメントが実行されないため、従業員データは表示されません。

ただし、FIND ステートメントでは IF NO RECORDS FOUND 節も提供されます。これにより、検索条件に一致するレコードがない場合に実行する処理を指定できます。

例:

** Example 'FINDX02': FIND (with IF NO RECORDS FOUND)
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 FIRST-NAME
END-DEFINE
*
FIND MYVIEW WITH NAME = 'BLACKSMITH'
  IF NO RECORDS FOUND
    WRITE 'NO PERSON FOUND.'
  END-NOREC
  DISPLAY NAME FIRST-NAME
END-FIND
END

上記のプログラムでは、NAME フィールドに BLACKSMITH の値があるすべてのレコードが選択されます。選択された各レコードについて、姓(NAME)と名前(FIRST-NAME)が表示されます。NAME = 'BLACKSMITH' のレコードがファイルに見つからない場合は、IF NO RECORDS FOUND 節内の WRITE ステートメントが実行されます。

プログラム FINDX02 の出力:

Page      1                                                  04-11-11  14:15:54
 
        NAME              FIRST-NAME
-------------------- --------------------
 
NO PERSON FOUND.

FIND ステートメントのその他の例

次の例のプログラムを参照してください。

HISTOGRAM ステートメント

以下のトピックについて説明します。

HISTOGRAM ステートメントの使用

HISTOGRAM ステートメントは、1 つのデータベースフィールドの値だけを読み込むか、または指定した検索条件に一致するレコード数を決定するために使用します。

HISTOGRAM ステートメントでは、HISTOGRAM ステートメントに指定されたもの以外のデータベースフィールドへのアクセスは提供されません。

HISTOGRAM ステートメントの基本構文

HISTOGRAM ステートメントの基本構文は次のとおりです。

HISTOGRAM VALUE INview FORfield

または、以下のように短くすることができます。

HISTOGRAMview FORfield

各項目の意味を次に示します。

view DEFINE DATA ステートメントで定義され、「データベースビューの定義」で説明されるビューの名前。
field そのビューで定義されるデータベースフィールドの名前。

完全な構文については、HISTOGRAM ステートメントのドキュメントを参照してください。

読み込む値の数の制限

READ ステートメントの場合と同様に、キーワード HISTOGRAM の後にカッコで囲んだ数字を指定することによって、読み込まれるレコード数を制限できます。

HISTOGRAM (6) MYVIEW FOR NAME

上記の例では、フィールド NAME の最初の 6 つの値だけが読み込まれます。

リミット表記がない場合は、すべての値が読み込まれます。

STARTING/ENDING 節

READ ステートメントと同様に、HISTOGRAM ステートメントでも、開始値と終了値を指定して読み込む値の範囲を絞り込むために、STARTING FROM 節と EENDING AT (or THRU) 節が提供されます。

例:

HISTOGRAM MYVIEW FOR NAME STARTING from 'BOUCHARD'
HISTOGRAM MYVIEW FOR NAME STARTING from 'BOUCHARD' ENDING AT 'LANIER' 
HISTOGRAM MYVIEW FOR NAME from 'BLOOM' THRU 'ROESER'

WHERE 節

HISTOGRAM ステートメントでも、値が読み込まれた、その値の処理が実行されるに評価される追加の選択条件を指定できる WHERE 節が提供されます。WHERE 節に指定するフィールドは、HISTOGRAM ステートメントの主節のフィールドと同じである必要があります。

HISTOGRAM ステートメントの例

** Example 'HISTOX01': HISTOGRAM
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 CITY
END-DEFINE
*
LIMIT 8
HISTOGRAM MYVIEW CITY STARTING FROM 'M'
  DISPLAY NOTITLE CITY 'NUMBER OF/PERSONS' *NUMBER *COUNTER
END-HISTOGRAM
END

上記のプログラムでは、システム変数 *NUMBER*COUNTERHISTOGRAM ステートメントで評価され、DISPLAY ステートメントで出力されます。には最後に読み込まれた値が含まれるデータベースレコードの数が入り、*COUNTER には読み込まれた値の合計数が入ります。

プログラム HISTOX01 の出力:

        CITY          NUMBER OF     CNT
                       PERSONS
-------------------- ----------- -----------
 
MADISON                        3           1
MADRID                        41           2
MAILLY LE CAMP                 1           3
MAMERS                         1           4
MANSFIELD                      4           5
MARSEILLE                      2           6
MATLOCK                        1           7
MELBOURNE                      2           8

MULTI-FETCH 節

MULTI-FETCH 節は、Adabas データベースのマルチフェッチレコード検索機能をサポートします。

この セクション で説明するマルチフェッチ機能は、ADA というタイプのデータベースに対してのみサポートされます。これは、コンフィグレーションユーティリティの DBMS 割り当てテーブルで定義できます。『コンフィグレーションユーティリティ』ドキュメントの「データベース管理システムの割り当て」を参照してください。MULTI-FETCH 節はデータベースタイプ ADA2 ではサポートされません。

以下のトピックについて説明します。

マルチフェッチ機能の目的

標準モードの Natural は、単一のデータベースコールでは複数のレコードを読み込みまず、フェッチごとに 1 つのレコードを取得するモードで常に稼働します。このような稼働は堅実で安定していますが、大量のデータベースレコードの処理には時間がかかる場合があります。これらのプログラムのパフォーマンスを向上させるために、マルチフェッチ処理を使用できます。

デフォルトでは、Natural はシングルフェッチを使用して Adabas データベースからデータを検索します。このデフォルトは Natural のプロファイルパラメータ MFSET を使用して設定できます。

ON(マルチフェッチ)および OFF(シングルフェッチ)の値でデフォルトの動作を定義します。MFSETNEVER に設定されると、Natural は常にシングルフェッチモードを使用し、ステートメントレベルでのすべての設定を無視します。

デフォルトの処理モードは、ステートメントレベルで変更することもできます。

サポートされるステートメント

マルチフェッチ処理は、データベース更新を伴わない次のステートメントに対してサポートされます。

構文の詳細については、FINDREAD または HISTOGRAM の各ステートメントの MULTI-FETCH 節に関する説明を参照してください。

マルチフェッチ使用時の考慮事項

同じ Adabas ファイルを参照するネストされたデータベースループで、内側のループの 1 つに UPDATE ステートメントが含まれる場合、Natural では更新後の値で外側のループの処理が続行されます。これは、マルチフェッチモードでは、外側のループのシーケンス制御に使用されるディスクリプタの値が内側のデータベースループによって更新される場合に、外側の論理 READ ループの位置を変更する必要があることを示します。このように処理することによって現在のディスクリプタに矛盾が発生した場合は、エラーが返されます。このような状況を避けるために、外側のデータベースループのマルチフェッチを無効にすることをお勧めします。

一般には、マルチフェッチモードによって、Adabas データベースにアクセスするときのパフォーマンスが改善されます。ただし、一部のケースで、特にデータベース更新が伴う場合は、パフォーマンスの向上にはシングルフェッチを使用する方が有利なときがあります。

データベース処理ループ

このセクションでは、FINDREAD、または HISTOGRAM の各ステートメントの結果としてデータベースから選択されたデータの処理に必要な処理ループについて説明します。

以下のトピックについて説明します。

データベース処理ループの作成

Natural では、FINDREAD、または HISTOGRAM ステートメントの結果としてデータベースから選択されたデータの処理に必要な処理ループが自動的に作成されます。

例:

次の例では、FIND ループを使用して、NAME フィールドに ADKINSON という値が含まれるすべてのレコードを EMPLOYEES ファイルから選択し、選択したレコードを処理します。この例では、選択された各レコードの特定のフィールドを表示する処理が含まれます。

** Example 'FINDX03': FIND
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 FIRST-NAME
  2 CITY
END-DEFINE
*
FIND MYVIEW WITH NAME = 'ADKINSON'
  DISPLAY NAME FIRST-NAME CITY
END-FIND
END

WITH 節に加えて、FIND ステートメントに WHERE 節が含まれる場合は、WITH 節の結果として選択されたレコードのうち、さらにWHERE 条件に一致するものだけが処理されます。

次の図は、データベース処理ループのフローロジックを示しています。

処理ループの階層

FIND または READ ステートメントあるいはその両方を複数使用することによって、次の例に示すように、処理ループの階層が作成されます。

処理ループの階層の例

** Example 'FINDX04': FIND  (two FIND statements nested)
************************************************************************
DEFINE DATA LOCAL
1 PERSONVIEW VIEW OF EMPLOYEES
  2 PERSONNEL-ID
  2 NAME
1 AUTOVIEW VIEW OF VEHICLES
  2 PERSONNEL-ID
  2 MAKE
  2 MODEL
END-DEFINE
*
EMP. FIND PERSONVIEW WITH NAME = 'ADKINSON'
  VEH. FIND AUTOVIEW WITH PERSONNEL-ID = PERSONNEL-ID (EMP.)
    DISPLAY NAME MAKE MODEL
  END-FIND
END-FIND
END

上記のプログラムでは、ADKINSON という名前のすべての従業員が EMPLOYEES ファイルから選択されます。選択された各レコード(従業員)は、その後、次のように処理されます。

  1. VEHICLES ファイルから車を選択するために、1 つ目の FIND ステートメントで EMPLOYEES ファイルから選択されたレコードの PERSONNEL-ID を選択条件に使用して、2 つ目の FIND ステートメントが実行されます。

  2. 選択された各従業員の NAME が表示されます。この情報は EMPLOYEES ファイルから取得されます。その従業員が所有する各車の MAKEMODEL も表示されます。この情報は VEHICLES ファイルから取得されます。

2 つ目の FIND ステートメントでは、次の図に示すように、1 つ目の FIND ステートメントの外部処理ループ内に内部処理ループが作成されます。

この図は、上述のプログラム例における処理ループの階層のフローロジックを示しています。

同じファイルにアクセスする FIND ループのネストの例

階層の両方のレベルで同じファイルが使用される処理ループの階層を構成することもできます。

** Example 'FINDX05': FIND (two FIND statements on same file nested)
************************************************************************
DEFINE DATA LOCAL
1 PERSONVIEW VIEW OF EMPLOYEES
  2 NAME
  2 FIRST-NAME
  2 CITY
1 #NAME (A40)
END-DEFINE
*
WRITE TITLE LEFT JUSTIFIED
  'PEOPLE IN SAME CITY AS:' #NAME / 'CITY:' CITY SKIP 1
*
FIND PERSONVIEW WITH NAME = 'JONES'
                WHERE FIRST-NAME = 'LAUREL'
  COMPRESS NAME FIRST-NAME INTO #NAME
  /*
  FIND PERSONVIEW WITH CITY = CITY
    DISPLAY NAME FIRST-NAME CITY
  END-FIND
END-FIND
END

上記のプログラムでは、まず姓が JONES で名前が LAUREL の従業員が EMPLOYEES ファイルからすべて選択されます。次に、同じ都市に住んでいるすべての従業員が EMPLOYEES ファイルから選択され、そのリストが作成されます。DISPLAY ステートメントで表示されるすべてのフィールド値は、2 つ目の FIND ステートメントから取得されます。

プログラム FINDX05 の出力:

PEOPLE IN SAME CITY AS: JONES LAUREL
CITY: BALTIMORE

        NAME              FIRST-NAME              CITY
-------------------- -------------------- --------------------

JENSON               MARTHA               BALTIMORE
LAWLER               EDDIE                BALTIMORE
FORREST              CLARA                BALTIMORE
ALEXANDER            GIL                  BALTIMORE
NEEDHAM              SUNNY                BALTIMORE
ZINN                 CARLOS               BALTIMORE
JONES                LAUREL               BALTIMORE

READ および FIND ステートメントのネストのその他の例

次の例のプログラムを参照してください。

データベース更新 - トランザクション処理

このセクションでは、トランザクションに基づいて Natural でデータベース更新処理が実行される方法について説明します。

以下のトピックについて説明します。

論理トランザクション

Natural では、トランザクションに基づいてデータベース更新処理が実行されます。つまり、すべてのデータベース更新要求は論理トランザクション単位で処理されます。論理トランザクションは、データベースに含まれている情報が論理的に一貫性を持っていることを確実にするために、完全に実行されなければならない最小の作業単位です。作業単位の定義はユーザーが行います。

論理トランザクションは、1 つ以上のデータベースファイルに関連する 1 つ以上の更新ステートメント(DELETESTOREUPDATE)で構成することができます。また、論理トランザクションは、複数の Natural プログラムにまたがることもできます。

論理トランザクションは、レコードが "ホールド" 状態におかれたときに開始します。Natural では、レコードが更新のために読み込まれるとき、例えば、FIND ループに UPDATE ステートメントや DELETE ステートメントが含まれる場合に、この処理が自動的に行われます。

論理トランザクションの終了は、プログラムの END TRANSACTION ステートメントによって決まります。このステートメントは、トランザクション内のすべての更新が正常に適用されたことを保証し、トランザクション中に "ホールド" 状態におかれていたすべてのレコードを解放します。

例:

DEFINE DATA LOCAL 
1 MYVIEW VIEW OF EMPLOYEES 
  2 NAME 
END-DEFINE 
FIND MYVIEW WITH NAME = 'SMITH' 
   DELETE 
   END TRANSACTION 
END-FIND 
END

選択された各レコードは "ホールド" 状態に置かれ、削除され、その後は END TRANSACTION ステートメントが実行されるときに "ホールド" 状態から解放されます。

注意:
Natural 管理者が設定する Natural プロファイルパラメータ ETEOP は、各 Natural プログラムの終了時に Natural で END TRANSACTION ステートメントを生成するかどうかを決定します。詳細については、Natural の管理者にお問い合わせください。

STORE ステートメントの例

次のプログラム例では、EMPLOYEES ファイルに新しいレコードを追加します。

** Example 'STOREX01': STORE  (Add new records to EMPLOYEES file)
*
** CAUTION: Executing this example will modify the database records!
************************************************************************
DEFINE DATA LOCAL
1 EMPLOYEE-VIEW VIEW OF EMPLOYEES
  2 PERSONNEL-ID(A8)
  2 NAME        (A20)
  2 FIRST-NAME  (A20)
  2 MIDDLE-I    (A1)
  2 SALARY      (P9/2)
  2 MAR-STAT    (A1)
  2 BIRTH       (D)
  2 CITY        (A20)
  2 COUNTRY     (A3)
*
1 #PERSONNEL-ID (A8)
1 #NAME         (A20)
1 #FIRST-NAME   (A20)
1 #INITIAL      (A1)
1 #MAR-STAT     (A1)
1 #SALARY       (N9)
1 #BIRTH        (A8)
1 #CITY         (A20)
1 #COUNTRY      (A3)
1 #CONF         (A1)   INIT <'Y'>
END-DEFINE
*
REPEAT
  INPUT 'ENTER A PERSONNEL ID AND NAME (OR ''END'' TO END)' //
        'PERSONNEL-ID : ' #PERSONNEL-ID    //
        'NAME         : ' #NAME  /
        'FIRST-NAME   : ' #FIRST-NAME
  /*********************************************************************
  /*  validate entered data
  /*********************************************************************
  IF #PERSONNEL-ID = 'END' OR #NAME = 'END'
    STOP
  END-IF
  IF #NAME = ' '
    REINPUT WITH TEXT 'ENTER A LAST-NAME'
            MARK 2 AND SOUND ALARM
  END-IF
  IF #FIRST-NAME = ' '
    REINPUT WITH TEXT 'ENTER A FIRST-NAME'
            MARK 3 AND SOUND ALARM
  END-IF
  /*********************************************************************
  /*  ensure person is not already on file
  /*********************************************************************
  FIP2. FIND NUMBER EMPLOYEE-VIEW WITH PERSONNEL-ID =  #PERSONNEL-ID
  /*
  IF *NUMBER (FIP2.) > 0
    REINPUT 'PERSON WITH SAME PERSONNEL-ID ALREADY EXISTS'
             MARK 1 AND SOUND ALARM
  END-IF
  /*********************************************************************
  /*  get further information
  /*********************************************************************
  INPUT
    'ENTER EMPLOYEE DATA'                            ////
    'PERSONNEL-ID             :' #PERSONNEL-ID (AD=IO) /
    'NAME                     :' #NAME         (AD=IO) /
    'FIRST-NAME               :' #FIRST-NAME   (AD=IO) ///
    'INITIAL                  :' #INITIAL              /
    'ANNUAL SALARY            :' #SALARY               /
    'MARITAL STATUS           :' #MAR-STAT             /
    'DATE OF BIRTH (YYYYMMDD) :' #BIRTH                /
    'CITY                     :' #CITY                 /
    'COUNTRY (3 CHARS)        :' #COUNTRY              //
    'ADD THIS RECORD (Y/N)    :' #CONF         (AD=M)
  /*********************************************************************
  /*  ENSURE REQUIRED FIELDS CONTAIN VALID DATA
  /*********************************************************************
  IF #SALARY < 10000
    REINPUT TEXT 'ENTER A PROPER ANNUAL SALARY' MARK 2
  END-IF
  IF NOT (#MAR-STAT = 'S'  OR = 'M' OR = 'D' OR = 'W')
    REINPUT TEXT 'ENTER VALID MARITAL STATUS  S=SINGLE ' -
                 'M=MARRIED D=DIVORCED W=WIDOWED' MARK 3
  END-IF
  IF NOT(#BIRTH = MASK(YYYYMMDD) AND #BIRTH = MASK(1582-2699))
    REINPUT TEXT 'ENTER CORRECT DATE' MARK 4
  END-IF
  IF #CITY  = ' '
    REINPUT TEXT 'ENTER A CITY NAME' MARK 5
  END-IF
  IF #COUNTRY = ' '
    REINPUT TEXT 'ENTER A COUNTRY CODE' MARK 6
  END-IF
  IF NOT (#CONF = 'N' OR= 'Y')
    REINPUT TEXT 'ENTER Y (YES) OR N (NO)' MARK 7
  END-IF
  IF #CONF = 'N'
    ESCAPE TOP
  END-IF
  /*********************************************************************
  /*  add the record with STORE
  /*********************************************************************
  MOVE #PERSONNEL-ID TO EMPLOYEE-VIEW.PERSONNEL-ID
  MOVE #NAME         TO EMPLOYEE-VIEW.NAME
  MOVE #FIRST-NAME   TO EMPLOYEE-VIEW.FIRST-NAME
  MOVE #INITIAL      TO EMPLOYEE-VIEW.MIDDLE-I
  MOVE #SALARY       TO EMPLOYEE-VIEW.SALARY (1)
  MOVE #MAR-STAT     TO EMPLOYEE-VIEW.MAR-STAT
  MOVE EDITED #BIRTH TO EMPLOYEE-VIEW.BIRTH (EM=YYYYMMDD)
  MOVE #CITY         TO EMPLOYEE-VIEW.CITY
  MOVE #COUNTRY      TO EMPLOYEE-VIEW.COUNTRY
  /*
  STP3. STORE RECORD IN FILE EMPLOYEE-VIEW
  /*
  /*********************************************************************
  /*  mark end of logical transaction
  /*********************************************************************
  END OF TRANSACTION
  RESET INITIAL #CONF
END-REPEAT
END

プログラム STOREX01 の出力:

ENTER A PERSONNEL ID AND NAME (OR 'END' TO END)
 
PERSONNEL ID :  
 
NAME         :
FIRST NAME   :

レコードホールドロジック

Natural を Adabas で使用する場合、更新するレコードは、END TRANSACTION または BACKOUT TRANSACTION ステートメントが発行されるまで、あるいはトランザクションタイムリミットを超えるまで、"ホールド" 状態におかれます。

1 人のユーザーに対してレコードが "ホールド" 状態におかれると、他のユーザーはそのレコードを更新できません。同じレコードを更新しようとする他のユーザーは、最初のユーザーがそのトランザクションを終了またはバックアウトしてレコードが "ホールド" から解放されるまで "待ち" 状態におかれます。

ユーザーが待ち状態におかれることを防ぐために、セッションパラメータ WH(ホールドレコードの待機)を使用できます。『パラメータリファレンス』を参照してください。

プログラムで更新ロジックを使用するときには、以下の点を考慮する必要があります。

  • レコードをホールド状態における最大時間は、Adabas のトランザクションタイムリミット(Adabas パラメータ TT)によって決まります。このタイムリミットを超えると、エラーメッセージが表示され、最後の END TRANSACTION 以降に行われたすべてのデータベース更新が取り消されます。

  • ホールドされるレコード件数およびトランザクションタイムリミットは、トランザクションのサイズ、つまり、プログラムにおける END TRANSACTION ステートメントの配置に影響されます。どこで END TRANSACTION を発行するかを決めるときには、再スタート機能を考慮する必要があります。例えば、処理中のレコードの大多数が更新されない場合は、レコードの "ホールド" 状態の制御には GET ステートメントが効率的です。これにより、複数の END TRANSACTION ステートメントの発行が回避され、ホールドされる ISN の数が少なくなります。大きなファイルを処理するときは、GET ステートメントでは追加の Adabas コールが必要となることに注意してください。GET ステートメントの例を次に示します。

ホールドロジックの例

** Example 'GETX01': GET (put single record in hold with UPDATE stmt)  
**                                                                     
** CAUTION: Executing this example will modify the database records!
***********************************************************************
DEFINE DATA LOCAL                                                      
1 EMPLOY-VIEW VIEW OF EMPLOYEES                                        
  2 NAME                                                               
  2 SALARY (1)                                                         
END-DEFINE                                                             
*                                                                      
RD. READ EMPLOY-VIEW BY NAME                                           
  DISPLAY EMPLOY-VIEW                                                  
  IF SALARY (1) > 1500000                                              
    /*                                                                 
    GE. GET EMPLOY-VIEW *ISN (RD.)                                     
    /*                                                                 
    WRITE '=' (50) 'RECORD IN HOLD:' *ISN(RD.)                         
    COMPUTE SALARY (1) = SALARY (1) * 1.15                             
    UPDATE (GE.)
    END TRANSACTION     
  END-IF                
END-READ                
END

トランザクションのバックアウト

アクティブな論理トランザクション中、つまり、END TRANSACTION ステートメントが発行される前に、BACKOUT TRANSACTION ステートメントを使用してトランザクションをキャンセルすることができます。このステートメントを実行すると、これまでに適用されたすべての更新(追加または削除されたすべてのレコードを含む)が削除され、トランザクションによってホールドされていたすべてのレコードが解放されます。

トランザクションの再スタート

END TRANSACTION ステートメントを使用して、トランザクション関連情報を保存することもできます。トランザクション処理が異常終了する場合は、GET TRANSACTION DATA ステートメントでこの情報を読み取り、トランザクションを再スタートするときにどこで処理を再開するかを確認できます。

トランザクションデータを使用したトランザクション再スタートの例

次のプログラムは、EMPLOYEES ファイルと VEHICLES ファイルを更新します。再スタート処理の後で、正常に処理された最後の EMPLOYEES レコードがユーザーに通知されます。ユーザーは、その EMPLOYEES レコードから処理を再開できます。再スタート処理の前に正常に更新された最後の VEHICLES レコードを、トランザクションの再スタートメッセージに含めるように設定することもできます。

** Example 'GETTRX01': GET TRANSACTION
*
** CAUTION: Executing this example will modify the database records!
************************************************************************
DEFINE DATA LOCAL
01 PERSON VIEW OF EMPLOYEES
  02 PERSONNEL-ID      (A8)
  02 NAME              (A20)
  02 FIRST-NAME        (A20)
  02 MIDDLE-I          (A1)
  02 CITY              (A20)
01 AUTO VIEW OF VEHICLES
  02 PERSONNEL-ID      (A8)
  02 MAKE              (A20)
  02 MODEL             (A20)
*
01 ET-DATA
  02 #APPL-ID          (A8) INIT <' '>
  02 #USER-ID          (A8)
  02 #PROGRAM          (A8)
  02 #DATE             (A10)
  02 #TIME             (A8)
  02 #PERSONNEL-NUMBER (A8)
END-DEFINE
*
GET TRANSACTION DATA #APPL-ID #USER-ID #PROGRAM
                     #DATE    #TIME    #PERSONNEL-NUMBER
*
IF  #APPL-ID NOT = 'NORMAL'     /* if last execution ended abnormally
AND #APPL-ID NOT = ' '
  INPUT (AD=OIL)
    //  20T '*** LAST SUCCESSFUL TRANSACTION ***' (I)
    /   20T '***********************************'
    /// 25T      'APPLICATION:' #APPL-ID
    /   32T             'USER:' #USER-ID
    /   29T          'PROGRAM:' #PROGRAM
    /   24T     'COMPLETED ON:' #DATE 'AT' #TIME
    /   20T 'PERSONNEL NUMBER:' #PERSONNEL-NUMBER
END-IF
*
REPEAT
  /*
  INPUT (AD=MIL) // 20T 'ENTER PERSONNEL NUMBER:' #PERSONNEL-NUMBER
  /*
  IF #PERSONNEL-NUMBER = '99999999'
    ESCAPE BOTTOM
  END-IF
  /*
  FIND1. FIND PERSON WITH PERSONNEL-ID = #PERSONNEL-NUMBER
    IF NO RECORDS FOUND
      REINPUT 'SPECIFIED NUMBER DOES NOT EXIST; ENTER ANOTHER ONE.'
    END-NOREC
    FIND2. FIND AUTO WITH PERSONNEL-ID = #PERSONNEL-NUMBER
      IF NO RECORDS FOUND
        WRITE 'PERSON DOES NOT OWN ANY CARS'
        ESCAPE BOTTOM
      END-NOREC
      IF *COUNTER (FIND2.) = 1     /* first pass through the loop
        INPUT (AD=M)
          /   20T 'EMPLOYEES/AUTOMOBILE DETAILS' (I)
          /   20T '----------------------------'
          /// 20T 'NUMBER:' PERSONNEL-ID (AD=O)
          /   22T   'NAME:' NAME ' ' FIRST-NAME ' ' MIDDLE-I
          /   22T   'CITY:' CITY
          /   22T   'MAKE:' MAKE
          /   21T  'MODEL:' MODEL
        UPDATE (FIND1.)            /* update the EMPLOYEES file
      ELSE                         /* subsequent passes through the loop
        INPUT NO ERASE (AD=M IP=OFF) //////// 28T MAKE / 28T MODEL
      END-IF
      /*
      UPDATE (FIND2.)              /* update the VEHICLES file
      /*
      MOVE *APPLIC-ID TO #APPL-ID
      MOVE *INIT-USER TO #USER-ID
      MOVE *PROGRAM   TO #PROGRAM
      MOVE *DAT4E     TO #DATE
      MOVE *TIME      TO #TIME
      /*
      END TRANSACTION #APPL-ID #USER-ID #PROGRAM
                     #DATE    #TIME    #PERSONNEL-NUMBER
      /*
    END-FIND                  /* for VEHICLES    (FIND2.)
  END-FIND                    /* for EMPLOYEES   (FIND1.)
END-REPEAT                    /* for REPEAT
*
STOP                          /* Simulate abnormal transaction end
END TRANSACTION 'NORMAL  '
END

ACCEPT/REJECT を使用したレコードの選択

このセクションでは、ユーザー指定の論理条件に基づいてレコードを選択するために使用する ACCEPT ステートメントおよび REJECT ステートメントについて説明します。

以下のトピックについて説明します。

ACCEPT および REJECT とともに使用可能なステートメント

ACCEPT ステートメントおよび REJECT ステートメントは、次のデータベースアクセスステートメントと連携して使用できます。

ACCEPT ステートメントの例

** Example 'ACCEPX01': ACCEPT IF
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 JOB-TITLE
  2 CURR-CODE (1:1)
  2 SALARY    (1:1)
END-DEFINE
*
READ (20) MYVIEW BY NAME WHERE CURR-CODE (1) = 'USD' 
ACCEPT IF SALARY (1) >= 40000
  DISPLAY NAME JOB-TITLE SALARY (1)
END-READ
END

プログラム ACCEPX01 の出力:

   Page      1                                                  04-11-11  11:11:11
                                                                                 
          NAME                  CURRENT            ANNUAL                  
                               POSITION            SALARY                  
  -------------------- ------------------------- ----------                
                                                                                 
  ADKINSON             DBA                            46700                
  ADKINSON             MANAGER                        47000                
  ADKINSON             MANAGER                        47000                
  AFANASSIEV           DBA                            42800                
  ALEXANDER            DIRECTOR                       48000                
  ANDERSON             MANAGER                        50000                
  ATHERTON             ANALYST                        43000                
  ATHERTON             MANAGER                        40000               

ACCEPT/REJECT ステートメントの論理条件基準

ACCEPT ステートメントおよび REJECT ステートメントを使用すると、READ ステートメントの WITH 節および WHERE 節で指定した論理条件に加えて、論理条件を指定できます。

ACCEPT/REJECT ステートメントの IF 節の論理条件基準は、レコードが選択されて読み込まれた後で評価されます。

論理条件演算子には次のものがあります。詳細については、「論理条件基準」を参照してください。

EQUAL EQ :=
NOT EQUAL TO NE ¬=
LESS THAN LT <
LESS EQUAL LE <=
GREATER THAN GT >
GREATER EQUAL GE >=

ACCEPT/REJECT ステートメントの論理条件基準は、ブール演算子 ANDOR、および NOT で結合することもできます。さらに、論理グループを示すためにカッコを使用することもできます。次の例を参照してください。

AND 演算子を指定した ACCEPT ステートメントの例

次のプログラムは、ACCEPT ステートメントでのブール演算子 AND の使用を示しています。

** Example 'ACCEPX02': ACCEPT IF ... AND ...
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 JOB-TITLE
  2 CURR-CODE (1:1)
  2 SALARY    (1:1)
END-DEFINE
*
READ (20) MYVIEW BY NAME WHERE CURR-CODE (1) = 'USD'
ACCEPT IF  SALARY (1) >= 40000
         AND SALARY (1) <= 45000
  DISPLAY NAME JOB-TITLE SALARY (1)
END-READ
END

プログラム ACCEPX02 の出力:

Page      1                                                  04-12-14  12:22:01
                                                                               
        NAME                  CURRENT            ANNUAL                        
                             POSITION            SALARY                        
-------------------- ------------------------- ----------                      
                                                                               
AFANASSIEV           DBA                            42800                      
ATHERTON             ANALYST                        43000                      
ATHERTON             MANAGER                        40000                     

OR 演算子を指定した REJECT ステートメントの例

次のプログラムは、REJECT ステートメントでブール演算子 OR を使用したものです。論理演算子が逆になっているため、前の例の ACCEPT ステートメントと同じ出力が生成されます。

** Example 'ACCEPX03': REJECT IF ... OR ...
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 JOB-TITLE
  2 CURR-CODE (1:1)
  2 SALARY    (1:1)
END-DEFINE
*
READ (20) MYVIEW BY NAME WHERE CURR-CODE (1) = 'USD'  
REJECT IF SALARY (1) < 40000
         OR SALARY (1) > 45000
  DISPLAY NAME JOB-TITLE SALARY (1)
END-READ
END

プログラム ACCEPX03 の出力:

Page      1                                                  04-12-14  12:26:27
                                                                               
        NAME                  CURRENT            ANNUAL                        
                             POSITION            SALARY                        
-------------------- ------------------------- ----------                      
                                                                               
AFANASSIEV           DBA                            42800                      
ATHERTON             ANALYST                        43000                      
ATHERTON             MANAGER                        40000                     

ACCEPT/REJECT ステートメントのその他の例

次の例のプログラムを参照してください。

AT START/END OF DATA ステートメント

ここでは、セクションステートメント AT START OF DATA および AT END OF DATA の使用方法について説明します。

以下のトピックについて説明します。

AT START OF DATA ステートメント

AT START OF DATA ステートメントは、データベース処理ループで一連のレコードの最初のレコードが読み込まれた後に実行する処理を指定するために使用します。

AT START OF DATA ステートメントは、処理ループ内に指定する必要があります。

AT START OF DATA 処理で出力が生成される場合は、最初のフィールド値の前に出力されます。デフォルトでは、この出力は左揃えでページに表示されます。

AT END OF DATA ステートメント

AT END OF DATA ステートメントは、データベース処理ループのすべてのレコードが処理された後に実行する処理を指定するために使用します。

AT END OF DATA ステートメントは、処理ループ内に指定する必要があります。

AT END OF DATA 処理で出力が生成される場合は、最後のフィールド値の後に出力されます。デフォルトでは、この出力は左揃えでページに表示されます。

AT START OF DATA/AT END OF DATA ステートメントの例

以下のプログラム例は、AT START OF DATA および AT END OF DATA ステートメントの使用法を示しています。

時刻を表示するために、Natural のシステム変数 *TIMEAT START OF DATA ステートメントに組み込まれています。

最後に選択された従業員の名前を表示するために、Natural のシステム関数 OLDAT END OF DATA ステートメントに組み込まれています。

** Example 'ATSTAX01': AT START OF DATA
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 CITY
  2 NAME
  2 JOB-TITLE
  2 INCOME  (1:1)
    3 CURR-CODE
    3 SALARY
    3 BONUS (1:1)
END-DEFINE
*
WRITE TITLE 'XYZ EMPLOYEE ANNUAL SALARY AND BONUS REPORT' / 
READ (3) MYVIEW BY CITY STARTING FROM 'E'
  DISPLAY GIVE SYSTEM FUNCTIONS
          NAME (AL=15) JOB-TITLE (AL=15) INCOME (1)
  /*
 AT START OF DATA
    WRITE 'RUN TIME:' *TIME /
  END-START
  AT END OF DATA
    WRITE / 'LAST PERSON SELECTED:' OLD (NAME) /
  END-ENDDATA
END-READ
*
AT END OF PAGE
  WRITE / 'AVERAGE SALARY:' AVER (SALARY(1))
END-ENDPAGE
END

プログラムが次の出力を生成します。

                  XYZ EMPLOYEE ANNUAL SALARY AND BONUS REPORT 
                                                              
     NAME           CURRENT                 INCOME            
                   POSITION                                   
                                CURRENCY   ANNUAL     BONUS   
                                  CODE     SALARY             
--------------- --------------- -------- ---------- ----------
                                                              
RUN TIME: 12:43:19.1                                          
                                                              
DUYVERMAN       PROGRAMMER      USD           34000          0
PRATT           SALES PERSON    USD           38000       9000
MARKUSH         TRAINEE         USD           22000          0
                                                              
LAST PERSON SELECTED: MARKUSH                                 
                                                              
                                                              
AVERAGE SALARY:      31333                                   

AT START OF DATA/AT END OF DATA のその他の例

次の例のプログラムを参照してください。

Unicode データ

Natural を使用すると、Adabas データベースのワイド文字フィールド(フォーマット W)にアクセスできます。

以下のトピックについて説明します。

データ定義モジュール

Adabas のワイド文字フィールド(W)は、Natural フォーマット U(Unicode)にマッピングされます。

フォーマット U の Natural フィールドの長さの定義は、フォーマット W の Adabas フィールドのサイズの半分に一致します。例えば、長さ 200 の Adabas のワイド文字フィールドは、Natural の (U100) にマッピングされます。

アクセスコンフィグレーション

Natural は Adabas からデータを受け取り、共通のエンコードとして UTF-16 を使用してデータを Adabas に送ります。

このエンコードは OPRB パラメータで指定され、オープン要求で Adabas に送られます。これはワイド文字フィールドに使用され、Adabas ユーザーセッション全体を通して適用されます。

制限

可変長のワイド文字フィールド(W)はサポートされていません。

照合ディスクリプタはサポートされていません。

Adabas および Unicode のサポートの詳細については、該当する Adabas 製品のドキュメントを参照してください。