DB2 V8 Javaアプリケーション用にSQLJを検討する

Connie Tsui (ctsui@ca.ibm.com), Staff Software Analyst , IBM 

Connie Tsuiは、IBMトロント研究所のDB2ソリューション・インテグレーション・チームに勤めるスタッフ・ソフトウェア・アナリストです。トロント大学でコンピューター・サイエンスの学士号を取得しました。現在の中心テーマは、DB2とWebSphereのインテグレーションです。



2003年 2月

はじめに

JavaTMを使ってリレーショナル・データにアクセスするには、SQLJとJDBCTMという2つの標準的な方法があります。IBM® DB2® Universal DatabaseTM(UDB)アプリケーションにはSQLJが適していると考えられているのはなぜでしょうか。それは、SQLJがすでにセキュリティー、パフォーマンス、簡素化を求めるアプリケーション・プログラマーに最適の言語となっているからです。この記事では、SQLJの背景に若干触れたあと、JDBCと比較したSQLJの利点について説明し、DB2 UDB Version 8.1が提供するSQLJの新しい機能および改善された機能を取り上げます。


SQLJの背景

1997年4月に、データベース・ベンダーは、Javaプログラミング言語に静的SQLステートメントおよびコンストラクトを使用する方法についてアイデアを交換するため、非公式のオープン・グループとして定期的に集合することを始めました。中心メンバーとなったのは、IBM、Oracle、Compaq、Informix®、Sybase、Cloudscape、Sun Microsystemsなどでした。グループは、開発を進めていた仕様に、当初、JSQLという名前を付けていましたが、JSQLが登録商標名であることがわかったあと、JSQLからSQLJに変更しました。1997年12月、Oracleは、Javaへの組み込みSQLの基準実装を他のメンバーに提供しました。この基準実装は、JDK 1.1をサポートする任意のプラットフォーム上で動作可能であり、ベンダー中立でした。1998年12月、JavaへのSQL組み込みの仕様が完成し、ANSI規格「Database Language - SQL, Part 10 Object Language Bindings(SQL/OLB)ANSI x3.135.10-1998」として受け入れられました。この仕様は一般に、SQLJ仕様のパート0と呼ばれています。現在は、SQL/OLB(Object Language Bindings)として知られています。

SQLJ仕様は、現在、2つのパートで構成されています。

  • SQL/OLB:JavaへのSQL組み込み
    規格のこのパートは、JavaメソッドへのSQL組み込みの構文と意味、および生成したSQLJアプリケーションのバイナリー移植性を保証するメカニズムを説明しています。これがこの記事のトピックです。
  • SQL/JRT:Javaプログラミング言語を使用するSQLルーチンと型
    規格のこのパートは、下記について取り上げています。

    • SQLストアード・プロシージャーとユーザー定義関数などのJava静的メソッドの呼び出しの仕様。SQLシステムへのJavaクラスのインストール、SQL関数やストアード・プロシージャーとしてのSQLでのJavaクラスの静的メソッドの呼び出し、指定したパラメーター出力値の取得、SQL結果セットの戻りのためのSQL拡張機能を定義しています。
    • SQLユーザー定義データ型として、Javaクラスを使用するための仕様。SQLでデータ型としてJavaクラスを使用するためのSQL拡張機能を定義しています。

用語:この記事ではこれ以降、SQLJという用語は、SQL/OLBのみを意味します。


SQLJプログラミング環境

HSSFを使って、Excelファイルに各種の操作を加えることができます。この記事で説明するように、単に数値や文字列のセル値を書き込むことはもちろんですが、それだけでなく、行や列のサイズの定義、セルのスタイルの設定(テキストを太字や斜体にする、境界線を挿入する、など)といったことも可能です。


アプリケーションのインストールと実行

SQLJ環境には、開発とランタイムの2つのフェーズがあります。このセクションでは、各フェーズに関係するコンポーネントとそのコンポーネント間の関係について説明します。

SQLJアプリケーションの開発
SQLJを使用するアプリケーションを開発するには、変換プログラム、プロファイル・カスタマイザー、プロファイル・バインダーの3つのコンポーネントが必要です。この3つのコンポーネントをサポートする機能を提供するユーティリティーは、それぞれ、sqlj、db2sqljcustomize、db2sqljbindです。図1にこのプロセスの概要を示します。

  1. 最初に、SQLJ変換プログラム(sqlj)を呼び出し、SQLJソース・ファイルを読み込んで、プログラムのSQLJ構文に問題がないかをチェックします。エラーがなければ、Javaソース・ファイルと0個以上のSQLJプロファイルが生成され、オプションで、生成したJavaソースがバイト・コード(デフォルト)にコンパイルされます。SQLランタイムを呼び出してSQL操作を実行する組み込みSQLは、生成されたJavaソース・ファイルに置き換わります。
  2. 次に、SQLJプロファイル・カスタマイザー(db2sqljcustomize)を呼び出して、生成された直列化プロファイルに対応するDB2カスタマイズを作成します。カスタマイザーは、オプション(デフォルト)で、動的に作成可能なSQLステートメントにオンライン・チェックを実行します。このオンライン・チェックで、構文、意味、スキーマの検証が実行されます。また、オプション(デフォルト)で、SQLJプロファイル・バインダーを呼び出してDB2パッケージのバインドも行います。
  3. プロファイルのカスタマイズ時に自動バインドを実行しないようにした場合は、別途SQLJプロファイル・バインダー(db2sqljbind)を呼び出して、カスタマイズ済みのSQLJプロファイルをデータベースにバインドすることができます。
  4. カスタマイズされているかいないかにかかわらず、プロファイルの内容を確認するには、SQLJプロファイル・プリンター(db2sqljprint)を使って、プロファイルの内容をテキスト形式で出力することができます。
    図1.SQLJ開発環境
    図1.SQLJ開発環境

SQLJアプリケーションの実行
SQLJランタイムは、JDBCドライバーを利用して、データベースへアクセスするためのデータベース接続を取得します。カスタマイズされていないSQLJアプリケーションは、任意のJDBC2.0ドライバーで実行可能です。カスタマイズされていないSQLJアプリケーションを実行するのは、開発時のテスト目的のみです。カスタマイズ済みのSQLJアプリケーションを実行するには、V8 CLIベースのJDBCタイプ2ドライバー、Universal JDBCドライバー(タイプ2またはタイプ4)を使って、データベース接続を確立することができます。このセクションでは、カスタマイズ済みSQLJアプリケーション用のランタイム環境についてのみ説明します。

SQLJアプリケーションを実行すると、SQLJランタイムが、カスタマイズ済みのプロファイルからSQL操作についての情報を読み取り、カスタマイズに格納されたパッケージ・キー情報(パッケージ名、パッケージ整合性トークン、コレクション名)に一致するDB2パッケージ内のステートメントを実行します。

図2.SQLJランタイム環境
図2.SQLJランタイム環境

JDBCと比較したSQLJの利点

SQLJとJDBCの仕様は両方とも、Javaを使ってリレーショナル・データベースへアクセスする方法を記述しています。このセクションでは、以下の側面から両者の相違を説明します。

表1は、これから説明するSQLJとJDBCの相違について要約したものです。

正常にログインできたら、図2に示すように、現在の接続で利用可能な表が入った画面が表示され、目的の表を選択することができます。

規格およびSQL仕様レベル

SQLJは、「ISO/IEC 9075-10:2000 Information technology -- Database languages -- SQL -- Part 10: Object Language Bindings(SQL/OLB)」の実装です。SQLJは、J2EEプラットフォームの一部ではありません。

JDBCは、J2SE 1.4とJ2EE 1.4プラットフォーム仕様の必須コンポーネントです。Java Software Development Kit(JDK)のバージョン1.1以降、JDKの中核部分となっています。java.sqlパッケージにも組み込まれています。JDBCドライバーは、なんらかの拡張を仕様に定義して、最低限Entry SQL-92ステートメントをサポートしなければなりません。

セキュリティー

SQLJにセキュリティー許可モデルが実装されていることが、ユーザーがSQLJの使用を検討する最大の理由です。静的SQLでは、セキュリティー特権がパッケージ作成者に割り当てられ、DB2パッケージに格納されます。

カスタマイズされたDB2 SQLJでは、SQLは静的に実行されます。したがって、SQLステートメントはパッケージ所有者の特権を使って実行されます。SQLJアプリケーションを実行する他のすべてのユーザーについては、パッケージにEXECUTE特権を付ける必要があります。つまり、適切な特権が明示的に与えられていない限り、プログラム実行の許可を与えられているユーザーが、必ずしも、プログラムが照会する、あるいは変更しようとしているテーブルまたはビューに対して、SELECT、UPDATE、DELETE、INSERTの権利を持っているわけではありません。

これに対して、JDBCアプリケーションのSQLステートメントは、データベースに接続しアプリケーションを実行するユーザーの特権によって実行されます。したがって、ユーザーには、テーブルにアクセスする特権が必要です。

パフォーマンス

SQLJで、SQLステートメントをJavaプログラムに組み込みできるのは、SQL-92で、C、COBOL、FORTRANその他のプログラミング言語にSQLステートメントを組み込みできるのに似ていますが、SQLJアプリケーションは、SQLJプロファイルのカスタマイズの有無に応じて、動的または静的に実行することが可能です。SQLJアプリケーションはプリコンパイルされ、SQLステートメントのパス長さは、パッケージがDB2データベースに格納される際に最適化されます。静的に実行されるSQLJアプリケーションは、JDBCよりも優れたパフォーマンスをもたらすことができます。

ここで推奨している静的実行を利用したい場合は、SQLJプロファイル・カスタマイザーを使ってプロファイルをカスタマイズすることが必要です。

JDBCでは、SQLステートメントは動的に実行されます。構文または意味エラーによる例外があれば、アプリケーション実行時に発生します。

静的または動的SQLステートメント処理は、DB2 UDBモニターを使って検証することができます。2つの監視方法として、スナップショット監視とイベント監視があります。スナップショット・モニターは、特定時点のデータベース・アクティビティーに関する情報を提供します。イベント・モニターは、DB2 UDBイベントの特定マイルストーンの発生を記録します。下記のリスト1は、JDBCプログラムから生成されたイベント・モニターの出力サンプルの抜粋です。「Type: Dynamic」は、SELECT job FROM staff WHERE name = ?ステートメントが動的に実行されたことを伝えています。

リスト1 JDBCプログラムから生成されたイベント・モニターの出力サンプル
 10) Statement Event ...
  Appl Handle: 23
  Appl Id: G91AA377.G576.00F306261BF2
  Appl Seq number: 0001

  Record is the result of a flush: FALSE
  -------------------------------------------
  Type     : Dynamic
  Operation: Prepare
  Section  : 1
  Creator  : NULLID
  Package  : SYSSH200
  Consistency Token  : SYSLVL01
  Package Version ID  :
  Cursor   : SQL_CURSH200C1
  Cursor was blocking: FALSE
  Text     : SELECT job FROM staff WHERE name = ?

リスト2は、SQLJプログラムから生成されたイベント・モニターの出力サンプルの抜粋です。出力中の「Type: Static」と「Package: SRQT402」は、ステートメントがSRQT402パッケージに対して静的に実行されたことを伝えています。

リスト2.SQLJプログラムから生成されたイベント・モニターの出力サンプル
10) Statement Event ...
  Appl Handle: 12
  Appl Id: G91ABD18.G47D.00F306C01D63
  Appl Seq number: 0001

  Record is the result of a flush: FALSE
  -------------------------------------------
  Type     : Static
  Operation: Execute
  Section  : 1
  Creator  : NULLID
  Package  : SRQT402
  Consistency Token  : SARoQCAp
  Package Version ID  :
  Cursor   :
  Cursor was blocking: FALSE

注:いくつかのステートメントは、カスタマイズされたSQLJプログラムでは正常に実行されますが、カスタマイズされていないSQLJプログラムでは正常に実行されません。一例として、両方向スクロール・カーソル上のUPDATE/DELETE WHERE CURRENT OFがあります。一般に、基礎となるJDBCドライバーにサポートされていない機能がある場合、カスタマイズされていないSQLJプログラムではその機能はサポートされません。

パフォーマンスのヒント:
singleton select照会では、SQLJが提供するSELECT INTO構文を使用することにより、大きなJDBC ResultSetsを任意に操作するときと比較して、ネットワーク・アクティビティーを軽減することができます。

図3は、singleton select照会のSQLJとJDBC構文を比較しています。

図3.単一行の検索−SQLJ対JDBC


SQLJ syntax:
#sql [conCtx] { SELECT job INTO :job FROM staff WHERE name = 
            :name };

JDBC syntax:
PreparedStatement pstmt = con.prepareStatement(
                  "SELECT job FROM staff WHERE name = ? FETCH FIRST 1 ROW ONLY" );
             ResultSet rs = pstmt.executeQuery();
             if ( rs.next() )
                job = rs.getString(1);
             else
                job = null;
             pstmt.close();

構文

図3を見ると、JDBCよりもSQLJ構文が単純であることがわかります。多くのJava開発者にとって、この単純さは魅力的です。一般に、SQLJモジュールは、JDBCモジュールよりも簡潔で、書き方も容易です。これは、開発サイクルが短く、開発コストや保守コストが低くなることを意味します。図4は、SQLJで、単一行データをデータベースに挿入するのがいかに簡単であるかを示しています。他の言語(CやCOBOLなど)で書いた既存の組み込みSQLアプリケーションがある場合は、SQLJを使ってアプリケーションを簡単にJavaに移行することができます。

図4.単一行の挿入 − SQLJ対JDBC

SQLJ構文:

sql [conCtx] { INSERT INTO sales VALUES(:date, :salesperson, :region, :sales) };

JDBC構文:

PreparedStatement pstmt = con.prepareStatement( "INSERT INTO sales VALUES (?, ?, ?, ?)" );

// set input parameter
pstmt.setObject(1, date);
pstmt.setString(2, salesperson);
pstmt.setString(3, region);
pstmt.setInteger(4, sales);
pstmt.executeUpdate();
pstmt.close();

SQLJとJDBCの相互運用性

SQLJ言語を使って、SQLJアプリケーションにJDBCステートメントを組み込むことができます。JDBCとSQLJ間のインタラクションを円滑にするため、SQLJには、同じアプリケーション内でSQLJ接続とJDBC接続間を共有し、SQLJイテレーターからJDBC結果セットを取得する方法、またはその逆の方法が用意されています。

SQLJアプリケーション内でJDBCを使用する必要があるのはどのようなときか
動的な操作、つまり、プログラムを作成する時点でSQL操作が不明な場合に、JDBCが必要です。リスト3は、JDBCを使ってSQLJプログラム内で動的照会(WHERE文節での名前は開発時点で不明)を実行する方法と、JDBCの結果セットをSQLJイテレーターに変える方法を示しています。

SQLJと異なり、JDBCはSQLJ構文を認識しません。また、SQLステートメントをJDBCアプリケーションに組み込むことはできません。

リスト3.JDBC結果セットからSQLJイテレーターへの変換
Public class ResultSetInterop
{
   #sql public static iterator Employees (String name, double salary);
   public static void main(String[] argv) throws SQLException
   {
      // the code for creating the SQLJ connection context (conCtx) and 
      // the Connection object (con) is omitted
      // create a JDBC statement object to execute a dynamic query
      Statement stmt = con.createStatement(); 
      String query = "SELECT name, salary FROM staff WHERE ";
      query += argv[0];
      ResultSet rs = stmt.executeQuery(query);
      Employees SalReport;
      // turn a JDBC result set to an SQLJ interator using the CAST statement
      #sql [conCtx] SalReport = { CAST :rs };

      while (SalReport.next()) {
         System.out.println( SalReport.name() + " earns " + SalReport.salary() );
      }
      SalReport.close();
      stmt.close();  
   }
   }

型チェックとスキーマ・チェック

SQLJは、Javaと同様に型指定の厳密な言語です。SQLJソース・ファイルからJavaソース・ファイルへの変換時に、SQLJ変換プログラムによりSQLJ構文がチェックされます。これは、他のDB2プリコンパイラーと同様です。また、Javaコンパイル時の変換フェーズでイテレーター・データ型変換が実行されます。たとえば、Javaコンパイラーは、(従業員給与などの)double型のイテレーター列がdouble型が許容されていない場所で使用されるのを防ぎます。したがって、String hv = employees.salary() の代入は、コンパイル時にエラーを生成します。また、プロファイルのカスタマイズ時にオンライン・チェックが実行されるので、プログラミング・エラーを早期にキャッチすることができます。

JDBCには、ランタイム前に構文または意味チェックを実行する機能はありません。構文または意味エラーによる例外があれば、アプリケーション実行時に発生します。

注:

  • オンライン・チェックは、従来のリリースでは変換フェーズで実行されていましたが、Version 8.1では、プロファイルのカスタマイズ時に実行されます。
  • ランタイムまでキャッチされないSQLJエラーがあります。また、動的に作成できないステートメントもオンライン・チェックされません。

相違点の要約

表1は、SQLJとJDBCの相違点を要約したものです。

表1.SQLJとJDBCの比較

    SQLJJDBC
規格ISO/ANSI(J2EEの一部ではない)Sun (part of J2EE)
SQL仕様レベルSQL-1999なし(最低限、Entry Level SQL-92のサポートが必要)
セキュリティー強力平均
パフォーマンス高速(開発時に静的アクセス・プランを作成低速(アプリケーション・プログラム実行時に動的アクセス・プランを作成)
構文高(簡潔)低(煩雑)
SQLJとJDBCの相互運用性ありなし
型チェックとスキーマ・チェック厳密(開発時に実行)緩やか(ランタイム時に実行)

Version 8.1の新しい特長

DB2 UDB Version 8.1には、新しい機能を搭載した新設計のSQLJドライバーが同梱されています。新しいSQLJドライバーは、分散リレーショナル・データベース体系TM(DRDAR)として知られるオープン分散プロトコルに基づいています。これをサポートするCLIベースのJDBCドライバー(タイプ2とタイプ3)、および新しいUniversal JDBCドライバー(タイプ2とタイプ4)がV8.1に採用されています。

SQLJの主な拡張は、次のように要約することができます。

新しいSQLJユーティリティーとランタイム

DB2 UDB Version 8.1のSQLJは、Pure Java SQLJユーティリティーとランタイム、および新しいオプションとオプション形式を実装しています。新しいランタイムにより、パフォーマンスはVersion 7に比べて格段に優れています。

Version 8.1では、SQLJ変換プログラムのsqljは、デフォルトで常に、生成されたJavaソースをコンパイルします。Version 7では、一部のJDKについてコンパイル・オプションが有効に使えず、手動でJavaファイルをコンパイルする必要がありました。

Version 8.1の新しいプロファイル・プリンターであるdb2sqljprintでは、開発者がURLを指定する必要がなくなりました。また、DB2ステートメント・タイプ、セクション番号、DB2結果セット・メタデータ情報など、実行するSQLステートメントに関する詳細な情報が提供されます。

プラットフォーム固有ファイルの解消

Version 8.1のSQLJプロファイル・カスタマイザーは、新しい直列化プロファイル形式を採用しており、DBRMファイルとバインド・ファイル(.bndファイル)の使用を解消しています。新しい形式は、すべてのプラットフォームに完全に移植可能です。すべてのBIND操作について、必要な情報のすべてが格納されており、ユーザーは、ターゲット・システム(UNIX®、Windows®、OS/390 、z/OSTM)上で直列化プロファイルを再カスタマイズする必要なく、任意のサーバー・プラットフォーム上で展開することができます。

Version 8の新機能

DB2 UDB V8.1の主な新機能には、次が含まれています。

DataSourcesを使った、SQLJ接続コンテキストの作成

Version 8.1 SQLJでは、SQLJ接続の作成用にJDBC DataSourceインタフェースを使用することができます。また、デフォルトの接続コンテキスト用の実装も変更されています。デフォルトの接続コンテキストを取得するために、SQLJランタイムは、jdbc/defaultDataSourceにJNDI検索を行います。何も登録されていない場合は、ドライバーがコンテキストにアクセスを試みたときに、nullコンテキスト例外がスローされます。したがって、JNDIにjdbc/defaultDataSourceを登録するか、または、DefaultContext.setDefaultContext(userctxt)を呼び出して、デフォルトのコンテキストを設定する必要があります。

推奨:SQLJ文節では明示的な接続コンテキストを使用してください。

リスト4.DataSourcesを使った、SQLJ接続コンテキストの作成
// Create connection context class Ctx with the new dataSource keyword
#sql public static context Ctx with (dataSource="jdbc/sampledb");

String userid, password;
String empname;

// Create connection context object conCtx for the connection to jdbc/sampledb
Ctx conCtx = new Ctx(userid, password);
#sql [conCtx] { SELECT lastname INTO :empname FROM emp WHERE empno = '000010' };

conCtx.close();

スクロール可能イテレーター

スクロール可能イテレーターを使って、前方、後方、特定行への移動ができます。JDBCの両方向スクロール・カーソルと同様に、非センシティブまたはセンシティブのどちらもあります。

  • 非センシティブ・イテレーターでは、イテレーターを開いたあと、基礎テーブルへの変更がイテレーターには見えません。非センシティブ・イテレーターは読み取り専用です。
  • センシティブ・イテレーターでは、イテレーターまたは他のプロセスにより基礎テーブルに加えられた変更がイテレーターに見えます。たとえば、リスト5のコードは、名前付きイテレーターを使って、従業員テーブルのすべての行から逆順で従業員番号と姓を検索する方法を示しています。
リスト5.スクロール可能イテレーターの使い方
//  Declare a scrollable iterator.
#sql  iterator ScrollIter implements sqlj.runtime.Scrollable with (sensitivity = SENSITIVE)
  (String EmpNo, String LastName);
{
  ScrollIter scrlIter;                                              
  #sql [conCtx] scrlIter={ SELECT empno, lastname FROM emp };                
 scrlIter.afterLast();                                              
  while (scrlIter.previous())                                     
  {
    System.out.println(scrlIter.EmpNo() + " " + scrlIter.LastName());   
  }
  scrlIter.close();                                                 
}

バッチ・アップデート

バッチ・アップデートを通じてステートメントをグループ化し、単一ラウンド・トリップを使って、実行用にバッチとしてデータベースに送ることができます。バッチ・アップデートには次のタイプのステートメントを含めることができます。

  • 検索されたINSERT、UPDATEまたはDELETEステートメント
  • CREATE、ALTER、DROP、GRANTまたはREVOKEステートメント
  • 入力パラメーターのみのCALLステートメント

JDBCと異なり、SQLJでは、入力パラメーターまたはホスト式を含むステートメントの入った異種バッチに対応します。したがって、同じステートメント、異なるステートメント、入力パラメーターまたはホスト式を含むステートメント、入力パラメーターまたはホスト式が含まれないステートメントのインスタンスを同じSQLJステートメント・バッチに結合することができます。

推奨: 
バッチをオフにする前に、または効率の悪いbatchモードがオンになったExecutionContextの使用を終了する前に、明示的にexecuteBatch() を呼び出てください。これにより、バッチに含まれているすべてのステートメントが確実に実行されることになります。

リスト6のコード・フラグメントは、バッチでアップデートを実行することにより、すべてのマネージャーの給与を上げる方法を示しています。

リスト6.バッチ・アップデートの実行
#sql iterator getMgr(String);     
{
  getMgr deptIter;           
  String mgrnum = null;        
  int raise = 400;              
   int currentSalary;
      String url = null, username = null, password = null;

  testContext conCtx = new testContext (url, username, password, false);
  // Acquire execution context.  
  // All statements that execute in a batch must use this execution context.
  ExecutionContext exeCtx = new ExecutionContext();     
  // Invoke ExecutionContext.setBatching (true) to create a batch.               
  exeCtx.setBatching(true);                                              

  #sql [conCtx] deptIter =  { SELECT mgrno FROM dept };
  #sql {FETCH :deptIter INTO :mgrnum};
  while (!deptIter.endFetch()) 
 {    
    #sql [conCtx] { 
      SELECT SALARY INTO :currentSalary FROM emp WHERE empno = :mgrnum};
    #sql [conCtx, exeCtx]                                           
      { UPDATE emp SET SALARY = :(currentSalary+raise) WHERE empno =:mgrnum };
    #sql { FETCH :deptIter INTO :mgrnum };
  }
  exeCtx.executeBatch();  
  exeCtx.setBatching(false);                                             
                                               
  #sql [conCtx] {COMMIT};                                               
  deptIter.close();      
  exeCtx.close();
  conCtx.close();                                                    
}

要約

SQLJのDB2実装は、JDBCと比較して明確な利点を提供します。より単純な構文、プリコンパイル時の型チェックとスキーマ・チェックは、開発コストを大きく引き下げます。また、SQLJアプリケーションにJDBCステートメントを組み込むための柔軟性もあります。これは、単一のアプリケーションが、SQLJとJDBCの両方の利点を活用できることを意味します。セキュリティーとパフォーマンスがJavaアプリケーションに重要である場合は、SQLJが正しい選択です。


詳細情報

参考文献

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Information Management
ArticleID=323366
ArticleTitle=DB2 V8 Javaアプリケーション用にSQLJを検討する
publish-date=022003