SQLJ アプリケーションにおける標識変数

SQLJ プログラムにおいて、標識変数を使用することにより、データ・サーバーとの間で NULL 値を受け渡ししたり、列のデフォルト値をデータ・サーバーに渡したり、ホスト変数値が未割り当てであることを通知したりすることができます。

ホスト変数またはホスト式の後に、標識変数を指定できます。 標識変数はコロン (:) で始まり、そのデータ・タイプは short です。 入力において、標識変数は、対応するホスト変数またはホスト式の値がデフォルト値か、null 以外の値か、null 値か、それとも割り当てられていないかを示します。 SQL ステートメントの中で変数に値が代入されていない場合、その変数とそのターゲット列が SQL ステートメント中に指定されていない場合と同じ結果になります。 出力において、標識変数は、対応するホスト変数またはホスト式の値が null 以外の値であるかそれとも null 値であるかを示します。

SQLJプログラムでは、null値を示す指示変数は、Javaのnull値をテーブルの列に代入するのと同じ機能を行います。 しかし、表から SQL NULL 値を取り出してホスト変数に入れるには、標識変数を使用する必要があります。

デフォルト値または未割り当て値を列に割り当てる標識変数を使用することにより、アプリケーションのコーディングを簡素化できます。 例えば、表に 4 個の列があり、それらの列の任意の組み合わせを更新しなければならないとすると、デフォルト標識変数や未割り当て標識変数を使用しない場合、可能なあらゆる組み合わせの更新を実行するために UPDATE ステートメントが 15 個必要になります。 デフォルト標識変数と未割り当て標識変数を使用すれば、SET ステートメントの中で 4 個の列すべてに対して 1 つの UPDATE ステートメントを使用することにより、可能なすべての更新を実行することができます。 標識変数を使用することにより、どの列をデフォルト値に設定するのか、またどの列は更新しないのかを指定することができます。

入力において、SQLJ では INSERT、UPDATE、または MERGE ステートメントに対して標識変数の使用がサポートされています。

SQLJ アプリケーションをカスタマイズする場合、SQLJ アプリケーションにおいて標識変数に以下の値のうちのいずれかを代入することにより、対応する入力ホスト変数のタイプを指定できます。

標識の値 相当する定数 値の意味
-1 sqlj.runtime.ExecutionContext.DBNull ヌル
-2, -3, -4, -6   ヌル
-5 sqlj.runtime.ExecutionContext.DBDefault デフォルト
-7 sqlj.runtime.ExecutionContext.DBUnassigned 未割り当て
short-value >=0 sqlj.runtime.ExecutionContext.DBNonNull null 以外

アプリケーションをカスタマイズしない場合、以下の値のうちいずれか 1 つを標識変数に代入することにより、対応する入力ホスト変数のタイプを指定できます。

標識の値 相当する定数 値の意味
-1 sqlj.runtime.ExecutionContext.DBNull ヌル
-7 <= short-value < -1   ヌル
0 sqlj.runtime.ExecutionContext.DBNonNull null 以外
short-value >0   null 以外

出力において、SQLJ では、以下のステートメントに対して標識変数の使用がサポートされています。

  • OUT または INOUT パラメーターを指定した CALL
  • FETCH 反復子 INTO ホスト変数
  • SELECT … INTO ホスト変数1、…ホスト変数n

SQLJ は、以下の値のうちいずれか 1 つを標識変数に代入することにより、SQL NULL 値が取り出されて対応するホスト変数に入れられたのかどうかを示します。

標識の値 相当する定数 値の意味
-1 sqlj.runtime.ExecutionContext.DBNull 取り出される値は SQL NULL
0   取り出される値は SQL NULL ではない

標識変数を使用して結果セットを更新することはできません。 結果セットに null 値またはデフォルト値を割り当てる場合、または列に値が割り当てられていないことを示す場合は、基礎となる SQLJ イテレーターの JDBC ResultSet オブジェクトに対して ResultSet.updateObject を呼び出します。

以下の例で、標識変数の使用方法を示します。

これらのどの例においても、データ・サーバーで拡張標識がサポートされていることが必要です。

INSERT で列にデフォルト値を割り当てるために標識を使用する例:

この例では、MGRNO 列と LOCATION 列にそれぞれのデフォルト値を設定する必要があります。 そのためには、コードの中で以下のステップを実行します。
  1. ターゲット列にデフォルトでない値を送信する入力ホスト変数 (dept、dName、 rptDept) に対応する標識変数 (deptInd、dNameInd、rptDeptInd) に、値 ExecutionContext.DBNonNull を代入します。
  2. ターゲット列にデフォルト値を送信する入力ホスト変数 (mgr、locn) に対応する標識変数 (mgrInd、locnInd) に、値 ExecutionContext.DBDefault を代入します。
  3. ホスト変数と標識変数の対を入力として指定した INSERT ステートメントを実行します。

選択されたステートメントの右にある番号は、前述のステップに対応しています。

import sqlj.runtime.*;
…
String dept = "F01";
String dName = "SHIPPING";
String rptDept = "A00";
String mgr, locn = null;
short deptInd, dNameInd, mgrInd, rptDeptInd, locnInd;
// Set indicator variables for dept, dName, rptDept to non-null
deptInd = dNameInd = rptDeptInd = ExecutionContext.DBNonNull;    1 
mgrInd = ExecutionContext.DBDefault;                             2 
locnInd = ExecutionContext.DBDefault;
#sql [ctxt]                                                      3 
  {INSERT INTO DEPARTMENT
    (DEPTNO, DEPTNAME, MGRNO, ADMRDEPT, LOCATION)
    VALUES (:dept :deptInd, :dName :dNameInd,:mgr :mgrInd,
    :rptDept :rptDeptInd, :locn :locnInd)};

UPDATE でデフォルト値を代入する標識を使用することにより列の値を未割り当てのままにする例:

この例では、F01 部門の行において、MGRNO 列はそのデフォルト値に設定し、DEPTNAME 列の値は RECEIVING に変更し、DEPTNO、DEPTNAME、 ADMRDEPT、および LOCATION の各列は未変更のままにする必要があります。 そのためには、コードの中で以下のステップを実行します。
  1. DEPTNAME 列のための新しい値を入力ホスト変数 dName に代入します。
  2. ターゲット列にデフォルト値を送信する入力ホスト変数 (mgr) について、標識変数 (mgrInd) に値 ExecutionContext.DBDefault を代入します。
  3. UPDATE 操作で未変更のままにすることが必要な入力ホスト変数 (dept、 dName、rptDept、および locn) について、標識変数 (deptInd、dNameInd、 rptDeptInd、および locnInd) に値 ExecutionContext.DBUnassigned を代入します。
  4. ホスト変数と標識変数の対を入力として指定した UPDATE ステートメントを実行します。

選択されたステートメントの右にある番号は、前述のステップに対応しています。

import sqlj.runtime.*;
…
String dept = null;
String dName = "RECEIVING";                                      1 
String rptDept = null;
String mgr, locn = null;
short deptInd, dNameInd, mgrInd, rptDeptInd, locnInd;
dNameInd = ExecutionContext.DBNonNull;
mgrInd = ExecutionContext.DBDefault;                             2 
deptInd = rptDeptInd = locnInd = ExecutionContext.DBUnassigned;  3 
#sql [ctxt]                                                      4 
  {UPDATE DEPARTMENT
    SET DEPTNO = :dept :deptInd,
        DEPTNAME = :dName :dNameInd,
        MGRNO = :mgr :mgrInd,
        ADMRDEPT = :rptDept :rptDeptInd,
        LOCATION = :locn :locnInd
    WHERE DEPTNO = "F01"
  };

列から NULL 値を取り出すために標識を使用する例:

この例では、HIREDATE 列から NULL 値が返される可能性があります。 その場合を処理するため、コードの中で以下のステップを実行します。
  1. HIREDATE から NULL 値が返された場合にそのことを示すための標識変数を定義します。
  2. ホスト変数と標識変数の対を出力として指定した FETCH ステートメントを実行します。
  3. 標識変数をチェックして NULL 値が返されたかどうかを調べます。

選択されたステートメントの右にある番号は、前述のステップに対応しています。

import sqlj.runtime.*;
…
#sql iterator ByPos(String, Date);  // Declare positioned iterator ByPos
{
  …
  ByPos positer;                    // Declare object of ByPos class
  String name = null;               // Declare host variables
  Date hrdate = null;
  short indhrdate = null;           // Declare indicator variable       1 
  #sql [ctxt] positer = 
    {SELECT LASTNAME, HIREDATE FROM EMPLOYEE};                         
                                    // Assign the result table of the SELECT
                                    // to iterator object positer
  #sql {FETCH :positer INTO :name, :hrdate :indhrdate };                2 
                                    // Retrieve the first row
  while (!positer.endFetch())       // Check whether the FETCH returned a row
  { if(indhrdate == ExecutionContext.DBNonNull {                        3 
     System.out.println(name + " was hired in " +
      hrdate); }
    else {
     System.out.println(name + " has no hire date "); }
    #sql {FETCH :positer INTO :name, :hrdate };
                                    // Fetch the next row
  }
  positer.close();                  // Close the iterator               5 
}

結果セット列にデフォルト値を割り当てる例

この例では、結果セットの HIREDATE 列をそのデフォルト値に設定する必要があります。 そのためには、コードの中で以下のステップを実行します。
  1. 取り出されたデータが入れられるイテレーターから、基礎となる ResultSet を取り出します。
  2. DB2PreparedStatement.DB_PARAMETER_DEFAULT 定数を指定した ResultSet.updateObject メソッドを実行することにより、結果セット列にデフォルト値を割り当てます。

選択されたステートメントの右にある番号は、前述のステップに対応しています。

#sql public iterator sensitiveUpdateIter 
 implements sqlj.runtime.Scrollable, sqlj.runtime.ForUpdate 
 with (sensitivity=sqlj.runtime.ResultSetIterator.SENSITIVE, 
 updateColumns="LASTNAME, HIREDATE") (String, Date);

  String name;                    // Declare host variables
  Date hrdate;

sensitiveUpdateIter iter = null;
#sql [ctx] iter = { SELECT LASTNAME, HIREDATE FROM EMPLOYEE};

iter.next();

java.sql.ResultSet rs =  iter.getResultSet();                       1 
rs.updateString("LASTNAME", "FORREST");
rs.updateObject
 (2, com.ibm.db2.jcc.DB2PreparedStatement.DB_PARAMETER_DEFAULT););  2,3 
rs.updateRow();
iter.close();