SQL 例

次のいずれかの方法で SQL データベースにアクセスできます。
どの事例でも、メモリー領域として SQL レコードを使用して、操作が正常に終了したかどうかを簡単にテストすることができます。 この節の例では、レコード・パーツが EGL ファイルに宣言されていること、および、そのパーツに基づいたレコードがそのファイルでプログラムに宣言されていることを前提としています。

SQL レコードおよび暗黙的なステートメントの詳細については、『SQL サポート』を参照してください。

SQL ステートメントのコーディング

SQL ステートメントをコーディングする準備として、変数を宣言します。
  empnum decimal(6,0);
  empname char(40);

SQL テーブルへの行の追加

行を追加する準備として、変数に値を割り当てます。
  empnum = 1;    empname = "John";
行を追加するには、次のように、EGL execute ステートメントを SQL INSERT ステートメントに関連付けます。
  try
    execute
      #sql{
        insert into employee (empnum, empname)
        values (:empnum, :empname)
      };
  onException
    myErrorHandler(8);
  end

SQL テーブルからの行セットの読み取り

SQL テーブルから行セットを読み取る準備として、レコード・キーを識別します。
  empnum = 1;  
データを取得するには、一連の EGL 文をコーディングします。
  • 結果セットを選択するには、EGL open 文を実行します。
      open selectEmp
        with #sql{
          select empnum, empname
          from employee 
          where empnum >= :empnum
          for update of empname 
        }
        into empnum, empname;
  • 結果セットの次の行にアクセスするには、EGL の get next 文を実行します。
      get next from selectEmp;
    open 文に into 文節を指定しなかった場合は、get next 文に into 文節を指定する必要があります。両方の文に into 文節を指定した場合は、get next 文の into 文節が優先されます。
      get next from selectEmp
        into empnum, empname;

    結果セットから最後のレコードが読み取られると、カーソルが自動的にクローズされます。

もっと複雑な例は、次のコードのとおりです。このコードは行セットを更新します。
  VGVar.handleHardIOErrors  = 1;

  try
    open selectEmp
      with #sql{
        select empnum, empname
        from employee 
        where empnum >= :empnum
        for update of empname 
      }
      into empnum, empname;
  onException
    myErrorHandler(6);    // プログラムを終了する
  end

  try
    get next from selectEmp;
  onException
    if (sqlcode != 100)
      myErrorHandler(8);  // プログラムを終了する
    end
  end

  while (sqlcode != 100) 
    empname = empname + " " + "III";

    try
      execute
        #sql{
          update employee 
          set empname = :empname
          where current of selectEmp
        };
    onException
      myErrorHandler(10); // プログラムを終了する
    end

    try
      get next from selectEmp;
    onException
      if (sqlcode != 100)
        myErrorHandler(8);  // プログラムを終了する
      end
    end
  end  // end while; 結果セットの最後の行が読み取られると
       // カーソルは自動的にクローズされる

  sysLib.commit();
get next および while 文をコーディングする代わりに、次のように結果セット内のそれぞれの行について文ブロックを実行する forEach 文を使用できます。
  VGVar.handleHardIOErrors  = 1;

  try
    open selectEmp
      with #sql{
        select empnum, empname
        from employee 
        where empnum >= :empnum
        for update of empname 
      }
      into empnum, empname;
  onException
    myErrorHandler(6);    // プログラムを終了する
  end

  try
    forEach (from selectEmp)
      empname = empname + " " + "III";
    
      try
        execute
          #sql{
            update employee 
            set empname = :empname
          where current of selectEmp
          };
      onException
        myErrorHandler(10); // プログラムを終了する
      end
    end  // end forEach 結果セットの最後の行が読み取られると
         // カーソルは自動的にクローズされる

  onException
    // 条件が "sqlcode = 100" の場合、forEach に関連した例外ブロックは実行されないので
    // "if (sqlcode != 100)" のテストは避ける。
    myErrorHandler(8);  // プログラムを終了する
  end

  sysLib.commit();

暗黙的な SQL ステートメントでの SQL レコードの使用

EGL SQL レコードの使用を開始するには、SQL レコード・パーツを宣言します。
  Record Employee type sqlRecord
    { 
      tableNames = [["employee"]],
      keyItems = ["empnum"],
      defaultSelectCondition =
        #sqlCondition{
          aTableColumn = 4   -- 各 SQL コメントは
                           -- 二重ハイフンで開始する
        }
    }

    empnum  decimal(6,0) {isReadonly=yes};
    empname char(40);
  end
レコード・パーツに基づいたレコードを宣言します。
  emp Employee;

SQL テーブルへの行の追加

SQL テーブルに行を追加する準備として、EGL レコードの値を格納します。
  emp.empnum = 1;    emp.empname = "John";
次の EGL add 文を指定してテーブルに従業員を追加します。
  try
    add emp;
  onException
    myErrorHandler(8);
  end

SQL テーブルからの行の読み取り

SQL テーブルから行を読み取る準備として、レコード・キーを識別します。
  emp.empnum = 1;  
以下のいずれかの方法で単一行を取得します。
  • 一連の文を生成するように EGL get 文を指定する (DECLARE cursor、OPEN cursor、FETCH row、および forUpdate がない場合は CLOSE cursor)。
      try
        get emp;
      onException
        myErrorHandler(8);
      end
  • 単一の SELECT ステートメントを生成するように EGL get ステートメントを指定する。
      try
        get emp singleRow;
      onException
        myErrorHandler(8);
      end
以下のいずれかの方法で複数の行を処理します。
  • EGL の open、get next、および while 文を使用する。
      VGVar.handleHardIOErrors  = 1;
    
      try
        open selectEmp forUpdate for emp;
      onException
        myErrorHandler(6);    // プログラムを終了する
      end
    
      try
        get next emp;
      onException
        if (emp not noRecordFound)
          myErrorHandler(8);  // プログラムを終了する
        end
      end
    
      while (emp not noRecordFound)
        myRecord.empname = myRecord.empname + " " + "III";
    
        try
          replace emp;
        onException
          myErrorHandler(10); // プログラムを終了する
        end
    
        try
          get next emp;
        onException
          if (emp not noRecordFound)
            myErrorHandler(8);  // プログラムを終了する
          end
        end
      end  // end while; 結果セットの最後の行が読み取られると
           // カーソルは自動的にクローズされる
    
      sysLib.commit();
  • EGL の open および forEach 文を使用する。
      VGVar.handleHardIOErrors  = 1;
    
      try
        open selectEmp forUpdate for emp;
      onException
        myErrorHandler(6);    // プログラムを終了する
      end
    
      try
        forEach (from selectEmp)
          myRecord.empname = myRecord.empname + " " + "III";
         
          try
            replace emp;
          onException
            myErrorHandler(10); // プログラムを終了する
          end
        end  // end forEach 結果セットの最後の行が読み取られると
             // カーソルは自動的にクローズされる
    
      onException
    
        // 条件が noRecordFound の場合、forEach に関連した例外ブロックは実行されないので
        // "if (not noRecordFound)" のテストは避ける
        myErrorHandler(8);  // プログラムを終了する
      end
    
      sysLib.commit();

明示的な SQL ステートメントでの SQL レコードの使用

明示的な SQL ステートメントで SQL レコードを使用するには、SQL レコード・パーツを宣言します。 このパーツと前のパーツは、SQL 項目プロパティーの構文および計算された値の使用方法が異なります。
  Record Employee type sqlRecord
    {
      tableNameVariables = [["empTable"]], 
                   // テーブル名変数を使用すると
                   // テーブルが実行時に指定されることを
                   // 意味する
      keyItems = ["empnum"]
    }
    empnum decimal(6,0) { isReadonly = yes };
    empname char(40);

    // 計算された列のプロパティーを指定する
    aValue decimal(6,0) 
      { isReadonly = yes,
        column = "(empnum + 1) as NEWNUM" };
  end
変数を宣言します。
  emp Employee;
  empTable char(40);

SQL テーブルへの行の追加

SQL テーブルに行を追加する準備として、EGL レコードとテーブル名変数に値を格納します。
  emp.empnum = 1;    emp.empname = "John";
  empTable = "Employee";
EGL add ステートメントを指定し、SQL ステートメントを変更してテーブルに従業員を追加します。
  // テーブル名変数の前にコロンは付かない
  try
    add emp
      with #sql{
        insert into empTable (empnum, empname)
        values (:empnum, :empname || ' ' || 'Smith')
      }

  onException
    myErrorHandler(8);
  end

SQL テーブルからの行の読み取り

SQL テーブルから行を読み取る準備として、レコード・キーを識別します。
  emp.empnum = 1;  
以下のいずれかの方法で単一行を取得します。
  • 一連の文を生成するように EGL get 文を指定する (DECLARE cursor、OPEN cursor 、FETCH row、CLOSE cursor)。
      try
        get emp into empname   // into 文節はオプション。(SELECT
                               // ステートメントには指定できない。)
        with #sql{
          select empname
          from empTable
          where empum = :empnum + 1
        }
      onException
        myErrorHandler(8);
      end
  • 単一の SELECT ステートメントを生成するように EGL get ステートメントを指定する。
      try
        get emp singleRow // into 文節は
                          // SQL レコードから派生し、
                          // select 文節内の列に基づく
        with #sql{
          select empname
          from empTable
          where empnum = :empnum + 1
        }
      onException
        myErrorHandler(8);
      end
以下のいずれかの方法で複数の行を処理します。
  • EGL の open、get next、および while 文を使用する。
      try
    
      // into 文節は
      // SQL レコードから派生し、
      // select 文節内の列に基づく
        open selectEmp forUpdate 
          with #sql{
            select empnum, empname
            from empTable
            where empnum >= :empnum
            order by NEWNUM       -- uses the calculated value
            for update of empname 
          } for emp;
      onException
        myErrorHandler(8);    // プログラムを終了する
      end
       
      try
        get next emp;
      onException
        myErrorHandler(9);    // プログラムを終了する
      end
    
      while (emp not noRecordFound)
        try
          replace emp
          with #sql{
            update :empTable
            set empname = :empname || ' ' || 'III'
          } from selectEmp;
    
        onException
          myErrorHandler(10);   // プログラムを終了する
        end
      
        try
          get next emp;
        onException
          myErrorHandler(9);    // プログラムを終了する
        end
      end  // end while
    
      // "close emp" は不要。emp は
      // 結果セットから最後のレコードが読み取られたとき、
      // または (例外の場合は) プログラム終了時に
      // 自動的にクローズされるため。
    
      sysLib.commit();
  • EGL の open および forEach 文を使用する。
      try
    
        // into 文節は
        // SQL レコードから派生し、
        // select 文節内の列に基づく
        open selectEmp forUpdate 
          with #sql{
            select empnum, empname
            from empTable
            where empnum >= :empnum
            order by NEWNUM       -- uses the calculated value
            for update of empname 
          } for emp;
    
      onException
        myErrorHandler(8);    // プログラムを終了する
      end
       
      try
        forEach (from selectEmp)
          
          try
            replace emp
            with #sql{
              update :empTable
              set empname = :empname || ' ' || 'III'
            } from selectEmp;
         
          onException
            myErrorHandler(9);  // プログラムを終了する
          end
    
        end   // forEach 文を終了する。
              // "close emp" は不要。emp は
              // 結果セットから最後のレコードが読み取られたとき、
              // または (例外の場合は) プログラム終了時に
              // 自動的にクローズされるため。
    
      onException
        // 条件が noRecordFound の場合、forEach に関連した例外ブロックは実行されないので
        // "if (not noRecordFound)" のテストは避ける
        myErrorHandler(9);  // プログラムを終了する
      end
    
      sysLib.commit();

EGL prepare 文の使用

EGL prepare ステートメントをコーディングする場合、オプションで SQL レコード・パーツを使用できます。 以下のパーツを宣言します。
  Record Employee type sqlRecord
    { 
      tableNames = [["employee"]],
      keyItems = ["empnum"],
      defaultSelectCondition = 
        #sqlCondition{
          aTableColumn = 4   -- 各 SQL コメントは
                            -- 二重ハイフンで開始する
        }
    }

    empnum  decimal(6,0) {isReadonly=yes};
    empname char(40);
  end
変数を宣言します。
  emp Employee;
  empnum02 decimal(6,0);
  empname02 char(40);
  myString char(120);

SQL テーブルへの行の追加

行を追加する前に、変数に値を割り当てます。
  emp.empnum = 1;    emp.empname = "John";
  empnum02 = 2;
  empname02 = "Jane";
SQL ステートメントを作成します。
  • EGL prepare ステートメントをコーディングし、SQL レコードを参照します。これにより、カスタマイズできる SQL ステートメントが提供されます。
      prepare myPrep
        from "insert into employee (empnum, empname) " +
        "values (?, ?)" for emp;
      
      // SQL レコードを使用して
      // 操作の結果をテストできる
      if (emp is error)
        myErrorHandler(8);
      end
  • あるいは、SQL レコードへの参照を使用せずに EGL prepare ステートメントをコーディングします。
      myString = "insert into employee (empnum, empname) " +
        "values (?, ?)";  
    
      try
        prepare addEmployee from myString;
      onException
        myErrorHandler(8);
      end
前の個々の事例では、EGL prepare 文に、EGL execute 文によって提供されるデータのプレースホルダーが含まれています。 次に execute 文の例を 2 つ示します。
  • レコード (SQL またはその他) から値を供給する場合:
      execute addEmployee using emp.empnum, emp.empname;
  • 個々の項目から値を供給する場合:
      execute addEmployee using empnum02, empname02;

SQL テーブルからの行の読み取り

SQL テーブルから行を読み取る準備として、レコード・キーを識別します。
  empnum02 = 2;
以下のいずれかの方法で複数の行を置換できます。
  • EGL の open、while、および get next 文を使用する。
      myString = "select empnum, empname from employee " + 
                 "where empnum >= ? for update of empname"; 
    
      try
        prepare selectEmployee from myString for emp;
      onException
        myErrorHandler(8);    // プログラムを終了する
      end
     
      try
        open selectEmp with selectEmployee 
          using empnum02 
          into emp.empnum, emp.empname;
      onException
        myErrorHandler(9);    // プログラムを終了する
      end
      
      try
        get next from selectEmp;
      onException
        myErrorHandler(10);   // プログラムを終了する
      end
    
      while (emp not noRecordFound)
                                        
        emp.empname = emp.empname + " " + "III";
    
        try
          replace emp
            with #sql{
              update employee 
              set empname = :empname
            }
          from selectEmp;
        onException
          myErrorHandler(11); // プログラムを終了する
        end
    
        try
          get next from selectEmp;
        onException
          myErrorHandler(12);   // プログラムを終了
        end
      end  // end while; 最後の行が読み取られると close が自動的に実行される
      sysLib.commit();
  • EGL の open および forEach 文を使用する。
      myString = "select empnum, empname from employee " + 
                 "where empnum >= ? for update of empname"; 
    
      try
        prepare selectEmployee from myString for emp;
      onException
        myErrorHandler(8);    // プログラムを終了する
      end
     
      try
        open selectEmp with selectEmployee 
          using empnum02 
          into emp.empnum, emp.empname;
      onException
        myErrorHandler(9);    // プログラムを終了する
      end
      
      try
        forEach (from selectEmp)
          emp.empname = emp.empname + " " + "III";
         
          try
            replace emp
              with #sql{
                update employee 
                set empname = :empname
              }
            from selectEmp;
          onException
            myErrorHandler(11); // プログラムを終了する
          end
        end  // forEach を終了する。最後の行が読み取られると close が自動的に実行される
      onException
    
        // 条件が noRecordFound の場合、forEach に関連した例外ブロックは実行されないので
        // "if (not noRecordFound)" のテストは避ける
        myErrorHandler(12);   // プログラムを終了
      end
    
      sysLib.commit();
ご利用条件 | フィードバック
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.(C) Copyright IBM Japan 2005.