...

PL/SQLからDB2 UDB v7.2 Javaへの移行ガイド 日本アイ・ビー・エム株式会社 ソフトウェア事業部

by user

on
Category: Documents
64

views

Report

Comments

Transcript

PL/SQLからDB2 UDB v7.2 Javaへの移行ガイド 日本アイ・ビー・エム株式会社 ソフトウェア事業部
PL/SQLからDB2 UDB v7.2 Javaへの移行ガイド
日本アイ・ビー・エム株式会社
ソフトウェア事業部
ソフトウェア・テクニカルサポート
DM 技術部
開発技術支援グループ
IBM Software Group
目次
1. はじめに ····································································································································· 1−1
1.1 目的 ····································································································································· 1−1
1.2 対象とする読者···················································································································· 1−1
1.3 おことわり··························································································································· 1−1
1.4 変更履歴 ······························································································································ 1−2
1.5 検証環境 ······························································································································ 1−3
1.6 商標 ····································································································································· 1−3
1.7 記号の意味··························································································································· 1−3
2. 移行方法 ····································································································································· 2−1
2.1 移行フロー··························································································································· 2−1
2.1.1 SPB を使用する移行手順·························································································· 2−3
2.1.2 SPB を使用しない移行手順 ······················································································ 2−4
2.2 基本的な PL/SQL から Java への構文比較 ········································································· 2−5
2.2.1 ブロック構造 ············································································································ 2−5
2.2.2 変数の宣言 ················································································································ 2−8
2.2.3 変数の代入 ·············································································································2−13
2.2.4 条件分岐·················································································································2−16
2.2.5 反復制御·················································································································2−17
2.2.6 カーソル処理 ·········································································································2−19
2.2.7 例外処理·················································································································2−22
2.3 考慮点·······························································································································2−24
2.3.1 戻り値を返す場合 ··································································································2−24
2.3.2 出力パラメーターにレコード型等の複合情報配列が含まれる場合 ·······················2−24
2.3.3 Oracle 組み込み関数、Oracle パッケージを使用している場合 ····························2−24
2.3.4 ストアード・プロシージャーをネストしている場合·············································2−24
2.3.5 ロックに対する考慮·······························································································2−25
3. サンプル ····································································································································· 3−1
3.1 サンプル・プログラムのリスト··························································································· 3−1
3.2 サンプル・プログラムを稼動させるための環境構築方法 ··················································· 3−2
3.2.1 DB2 UDB の環境構築方法 ······················································································· 3−2
3.2.2 Oracle の環境構築方法 ····························································································· 3−2
3.3 サンプルコード 1················································································································· 3−3
3.4 サンプルコード 2················································································································· 3−5
3.5 サンプルコード 3················································································································· 3−7
3.6 サンプルコード 4················································································································· 3−9
4. 付録············································································································································· 4−1
4.1 SPB「Java ストアード・プロシージャー作成ウィザード」による作成手順 ····················· 4−1
4.2 PL/SQL の登録内容参照および実行確認に関するコマンド例 ············································ 4−5
IBM Software Group
4.3 PL/SQL,DB2Java データタイプマッピング ······································································· 4−7
IBM Software Group
1.はじめに
1.1
目的
Oracle で開発されたシステムを DB2 UDB へ移行する際、アプリケーションの移行も必須となります。
なかでも PL/SQL で開発されたアプリケーションはほとんどの Oracle 環境で使用されています。本ガ
イドでは、Oracle PL/SQL ストアード・プロシージャーに焦点をあて(※)、DB2 UDB Java ストアード・
プロシージャーへの移行する方法を紹介します。なお本ガイドで紹介している移行方法は、PL/SQL を
できるだけ手間をかけずに DB2Java 化することを意識して以下を提供しています。
・
構文比較
・
サンプルコード(移行元の PL/SQL のソース)
・
サンプルコード(移行先の Java のソース)
・
開発手順(ストアード・プロシージャーの作成方法、動作確認方法)
これらにより、実際の移行作業の際に、すみやかに移行するための情報の提供を目的としています。
(※)PL/SQL で開発されるアプリケーションにはストアード・プロシージャーの他にストアード・ファ
ンクション、パッケージがありますが、本ガイドではそれらは割愛させていただきます。
なお、本ガイドでは以下のように製品名、名称を次のように省略して表記しています。
Oracle PL/SQL ストアード・プロシージャー
:PL/SQL
DB2 UDB Java ストアード・プロシージャー
:DB2Java
ストアード・プロシージャー・ビルダー
:SPB
1.2
対象とする読者
本ガイドでは、Oracle PL/SQL ストアード・プロシージャーを DB2 UDB Java ストアード・プロシージ
ャーへ移行するにあたり、その設計・開発に携わる方を対象とします。また、Oracle、DB2 UDB、PL/SQL、
Java および JDBC に関する基礎的な知識があることを前提とします。
1.3
おことわり
本ガイドはあくまで情報の提供であり、内容について正確な記述に努めましたが、本ガイドの内容に
対して何らかの保証をするものではなく、本ガイドを運用した結果についての一切の責任を負いませ
ん。
IBM Software Group
1−1
1.4
変更履歴
Version
初版
IBM Software Group
Date
2002/12/12
Notes
初版
1−2
1.5
検証環境
本ガイドは以下の環境を前提としています。したがって掲載しているサンプル、手順等は環境が異な
ると動作しない可能性があります。
OS: Windows 2000 Professional
DB2 UDB: DB2 UDB EE 7.2 + Fixpack6
Oracle: Oracle 8i
開発ツール: ストアード・プロシージャー・ビルダー
1.6
商標
Oracle は、米国オラクルの商標または登録商標です。
Windows 2000 は、Microsoft Corp.の商標または登録商標です。
DB2 UDB は、IBM Corporation の商標または登録商標です。
本ガイドに使用されているその他の会社名、製品名は各社の商標または登録商標です。
1.7
記号の意味
本ガイドでは記号を次のような意味に使用しています。
「∼」
:キーワード
(∼)
:補足、同義語
、
(矢印)
(2 重線矢印)
IBM Software Group
:手順・処理等の流れ
:移行前・移行後の関係、紐付
1−3
2.移行方法
2.1
移行フロー
PL/SQL から DB2Java に移行する際の目安として、移行作業手順とチェックポイントを移行フローとし
て以下に記載します。
・開発方法の選択
ここでは、ストアード・プロシージャーを作成、インストール、およびテストするための使いやす
い開発環境を提供している SPB(※1)を利用するかしないか、あるいは利用できるかできないかの判
断をします。
要件確認
利用しない
SPB の利用
利用したい(※2)
SPB を使用する移行方法
SPB を使用しない移行方法
(※1)ストアード・プロシージャーを開発する際、SPB を使用しなければならないというこ
とはありません。SPB を使用しなくても DB2 Java の開発は問題なくできます。SPB を利用す
るメリットは Java ファイルのコンパイル、Class ファイルの配置、Create Procedure 文の
作成・実行を自動的に行ってくれる点です。
(※2)標準では JDBC1.0 の環境となります。JDBC2.0 を利用する際には以下のような設定が
必要となります。(斜字体は環境に依存します。)
・ Db2spb.ini の編集
<DB2 UDB インストールディレクトリー>¥spb¥db2spb.ini に以下の行を追加します。
BUILD_JDK_HOME= C:¥PROGRA 1¥SQLLIB¥java¥java12¥jdk
・ データベース・マネージャー構成パラメーター「JDK11_PATH」の設定
以下のようにコマンドを実行します。
db2 update dbm cfg using JDK11_PATH C:¥PROGRA 1¥SQLLIB¥java¥java12¥jdk
・ DB2 レジストリー変数「DB2_USE_JDK12」の設定
以下のようにコマンドを実行します。
db2set DB2_USE_JDK12=ON
IBM Software Group
2−1
・移行にあたっての考慮点
移行するにあたって、DB2Java では PL/SQL の機能に対応していない部分があります。そういった未
対応の機能を使用していた場合には、そのケースごとに対応していく必要があります。なお、本ガ
イドで紹介している考慮すべき点は、未対応の機能をすべて網羅しているわけではありません。そ
れ以外のケースに遭遇した場合にもなんらかの対策が必要となります。
移行元 PL/SQL ソースを解析
Yes
戻り値を返す
No
出力パラメーターにレコード
Yes
型等の複合情報配列等が含ま
れている
No
Oracle 組み込み関数、あるいは
Yes
Oracle パッケージを使用して
いる
No
ストアード・プロシージャーか
Yes
らストアード・プログラムを呼
び出している。(ネストしてい
る。
)
No
ロックを意識した作りになっ
ている
Yes
No
特に対策は不要。ガイドの構文
何らかの対策が必要。本ガイド
比較、サンプルを参考に移行し
てください。
の「2.3 後述の考慮点」を参照
してください。
IBM Software Group
2−2
2.1.1 SPB を使用する移行手順
SPB を利用する移行手順の概要を以下に示します。
(1) ソース・ファイルの作成
本ガイドの「2.2 構文比較」を参考に DB2Java のソース・ファイル(.java)を作成します。
(2) DB2Java の登録
SPB の「Java ストアード・プロシージャー作成ウィザード」を使用して、DB2 UDB に DB2Java
を登録します。詳細な使用方法については、「4.1 付録」を参照してください。
(2) DB2Java の動作確認
DB2Java の動作が移行前の PL/SQL の動作と比較して同じ動作であるかを確認します。
動作確認に SPB を使用する場合は、SPB の「実行/デバッグ」機能を使用します。
・作成したプロシージャーはウィンドウのツリーリストに追加されます。
・ツリーリストからプロシージャーを選択し、メニュー(選択→実行)で実行されます。
・入力値の設定は以下の「変数値の指定」ダイアログで設定します。
・実行結果は以下の形式で表示されます。
IBM Software Group
2−3
2.1.2 SPB を使用しない移行手順
SPB を利用せず手作業で移行する手順の概要を以下に示します。
(1) ソース・ファイルの作成
本ガイドの「2.2 構文比較」を参考に DB2Java のソース・ファイル(.java)を作成します。
(2) クラスファイルの生成
SDK の「javac」コマンドによりソース・ファイルをコンパイルし、クラスファイル(.class)
を生成します。
>javac XXX.java
(3) クラスファイルの配置
生成したクラスファイルを DB2 UDB のインストールディレクトリ直下にある「function」デ
ィレクトリに配置します。DB2 UDB が標準インストールならば「SQLLIB」の直下にディレク
トリは存在します。
(4) DB2Java のデータベースへの登録
登録対象の DB2 UDB に接続して「Create Procedure」コマンドを実行し、DB2Java をデータ
ベースに登録します。
コマンドの各項目の詳細については本ガイドの「3 サンプル」を参照してください。
>db2 CREATE PROCEDURE XXX
省略
DB20000I SQL コマンドが正常に終了しました。
コマンドライン入力以外の登録方法には以下のファイル入力方式も可能です。
ファイル入力方式については本ガイドの「3 サンプル」を参照してください。
>db2 ‐ tvf Sample1.bld
DB20000I SQL コマンドが正常に終了しました。
(5) DB2Java の動作確認
DB2Java 移行後の動作を確認する。
DB2Java の動作が移行前の PL/SQL の動作と比較して同じ動作であるかを確認します。確認方
法は本ガイドの「4.2 付録」を参照してください。
IBM Software Group
2−4
2.2
基本的な PL/SQL から Java への構文比較
移行手順に沿って DB2Java のソース・ファイルを作成する際に、特に注意が必要な PL/SQL と DB2Java
のプログラム構文を、本章では移行元と移行先を比較する形式で記載します。
2.2.1 ブロック構造
PL/SQL のプロシージャーを DB2Java のプロシージャーへ移行する際、移行する対象の構文等を配置
する基礎となるプロシージャーのブロック構造を、最初に考慮する必要があります。
PL/SQL のブロック構造を移行する際には、プロシージャー呼び出し部を含むメインブロックとサブ
ルーチンのネストされたブロック、および各ブロックでの変数宣言について検討を行います。
(1) メインブロックのメソッド化
PL/SQL のブロック構造は、DB2Java ではクラスのメソッドに移行します。
PL/SQL でプロシージャー名称とそれに続く最上位の BEGIN∼END で範囲が示されたメインブロッ
クは、DB2Java では唯一のエントリー・ポイントとなるメインのメソッド、およびメインメソッ
ドを含むクラスに移行します。
⇒以下はサンプルコード 1 より抜粋したコードです。
PL/SQL
CREATE PROCEDURE SAMPLE1
引数(省略)
IS
変数(省略)
BEGIN
処理内容(メイン)
END SAMPLE1;
DB2Java
public class Sample1
{
変数(省略)
public static void sample1 ( 省略 )
{
処理内容(メイン)
}
}
・PL/SQL のプロシージャー名をメソッド名、およびクラス名に移行する際には Java のコーディ
ング規約(大文字/小文字等)に沿った名称となります。
・DB2Java として登録するためには、移行後のメインメソッドを「public」、「static」、「void」
で定義する必要があります。
IBM Software Group
2−5
(2) ネストされたブロック(サブブロック)のメソッド化
PL/SQL のブロック構造では、定義範囲をネストすることでサブルーチンを構成しています。
ネストされたブロックをメソッドに移行する場合には、移行前のブロックが PL/SQL の内部以外で
は利用不可能であった点に考慮して、同様に自身のクラス内部以外からは呼び出しを禁止する構
造に移行する必要があります。
対策としてメソッドのアクセス指定子を“private”に設定することで実現します。
⇒以下はサンプルコード 1 より抜粋したコードです。
PL/SQL
CREATE PROCEDURE SAMPLE1
引数
IS
変数宣言(メイン)
BEGIN
処理内容(メイン)
GOTO SUB1;
<<SUB1_RETURN>>
GOTO MAIN_END;
DB2Java
public class Sample1
{
変数宣言(メイン)
public static void sample1(引数)
{
処理内容(メイン)
sub1();
}
メソッドの呼び出し
ブロックの呼び出し
<<SUB1>>
DECLARE
変数宣言(サブ)
BEGIN
処理内容(サブ)
GOTO SUB1_RETURN;
END;
private static void sub1()
{
変数宣言(サブ)
処理内容(サブ)
}
}
<<MAIN_END>>
END SAMPLE1;
IBM Software Group
2−6
(3) 変数宣言
PL/SQL のネストされたブロックに配置された変数は、その有効範囲(スコープ)がネストの内部に
限定されています。
DB2Java に移行する際は、同様の有効範囲を持つように変数宣言する必要があります。
⇒以下はサンプルコード 1 より抜粋したコードです。
PL/SQL
CREATE PROCEDURE SAMPLE1
引数
IS
変数宣言(メイン)
BEGIN
メイン有効範囲
処理内容(メイン)
<<SUB1>>
DECLARE
変数宣言(サブ)
BEGIN
処理内容(サブ)
END;
DB2Java
public class Sample1
{
変数宣言(メイン)
public static void sample1(引数)
{
処理内容(メイン)
sub1();
}
サブ有効範囲
private static void sub1()
{
変数宣言(サブ)
処理内容(サブ)
}
END SAMPLE1;
}
IBM Software Group
2−7
2.2.2 変数の宣言
変数の宣言を移行する際の注意点として、入出力変数と特殊属性による変数の宣言があります。
特殊属性では%TYPE 属性、RECORD 型、TABLE 型について記載します。
(1) 入出力引数
PL/SQL の入出力引数はプロシージャー全体が有効範囲ですが、DB2Java に移行した構造では入出
力引数がメイン・メソッドのローカル変数扱いとなるため、有効範囲もメイン・メソッドに制限
される問題が発生します。
PL/SQL
CREATE PROCEDURE SAMPLE1
入出力引数
IS
BEGIN
参照更新可能
処理内容(メイン)
<<SUB1>>
BEGIN
処理内容(サブ)
END;
参照更新可能
END SAMPLE1;
IBM Software Group
DB2Java
public class Sample1
{
public static void sample1(入出力引数)
{
処理内容(メイン)
}
参照更新可能
private static void sub1()
{
処理内容(サブ)
}
参照不能、更新不能
}
2−8
この問題の対策として移行では、出力引数、入力引数、入出力引数をクラス変数(フィールド)に
変換し、クラス全体での共通な変数とします。
変換作業では入出力引数の利用する内容に合わせて以下の手順を考慮します。
①入出力引数を収めるクラス変数を用意する
②入出力引数を使用するメソッドを呼出す前にクラス変数にコピーする
③メソッド内で変更したクラス変数はメソッドの呼び出し後に入出力引数に戻す
⇒以下は変数の流れを図示しています。
DB2Java
public class Sample1
{
クラス変数
①
メインメソッド(入出力引数)
{
クラス変数にコピー
②
サブメソッド呼び出し
入出力引数に戻す
③
}
private static void サブメソッド()
{
クラス変数を参照、更新
}
}
⇒以下はコード例です。
PL/SQL
CREATE PROCEDURE SAMPLE1
引数 A
IS
変数宣言(メイン)
BEGIN
処理内容(メイン)→ A の参照/変更可能
<<SUB1>>
DECLARE
変数宣言(サブ)
BEGIN
処理内容(サブ)→ A の参照/変更可能
END;
END SAMPLE1;
IBM Software Group
DB2Java
public class Sample1
{
変数宣言(メイン)
① private static 型 a →(引数 A の代用)
public static void sample1(引数 A)
{
処理内容(メイン)→ A の参照/変更可能
②
a = A; →(引数 A を a に置き換える)
sub1();
③
A = a; →(変数 a から A を復帰する)
}
private static void sub1()
{
変数宣言(サブ)
処理内容(サブ)
×操作 A → A の利用不可能
○操作 a → サブ内では a を利用する
}
}
2−9
・注意点 1
DB2Java ではデータ型として、本ガイドの「4.3 PL/SQL,DB2Java データタイプマッピング」
に記載されたものが利用できます。
・注意点 2
出力引数および入出力引数は、DB2Java の 1 つの要素を持つ配列として定義します。
出力値および入出力値の受け渡しは、配列[0]に対する代入に移行します。
出力引数および入出力引数の受け渡しに配列[0]以外は使用できません。
出力引数によるカーソルの受け渡しは、引数に「ResultSet」型の配列を使用し、
結果セットを返します。
・注意点 3
本ガイドではクラス変数に変換する方式を記載していますが、次のようにプロシージャーの
入出力引数をサブメソッドの引数に追加する方式等でも移行できます。
⇒以下の図は、変数の流れを示しています。
DB2Java
public class Sample1
{
メインメソッド(引数1、引数2、
・・・)
{
サブメソッド呼び出し(
本来の引数、
引数1、
引数2、
・・・
)
}
private static void サブメソッド(
本来の引数、
引数1、
引数2、
・・・
)
{
引数1、引数2、・・・を参照、更新
}
}
IBM Software Group
2−10
(2) %TYPE 属性
PL/SQL での%TYPE 属性による変数宣言は、DB2Java では%TYPE 属性が指定するカラムのデータ型と
データ長を、変数宣言で明示的に型を指定する必要があります。
⇒以下はサンプルコード 2 より抜粋したコードです。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE2(
W_IN_NO IN EMP.EMPNO %TYPE ,
DB2Java
public class Sample2
{
public static void sample2(
short w_in_no,
)
省略
) AS
省略
・DB2Java ではデータ型として、本ガイドの「4.3 PL/SQL,DB2Java データタイプマッピング」に
記載されたものが利用できます。
・上の例で、PL/SQL では%TYPE 属性で宣言された上記抜粋コードの入力引数は、表「EMPLOYEE」
の列「EMPNO」のデータ型(NUMBER)を暗黙的に保持しています。それに対して DB2Java では、%TYPE
属性に相当するものがないため、明示的に「NUMBER(4)」に対応する、
「short」型により変数宣
言を行っています。
(3) RECORD 型
PL/SQL での RECORD 型による変数宣言は、DB2Java では複数の情報を保持するクラスを作成し、そ
のクラスのインスタンスを生成することで対応できます。
ただし PL/SQL で引数として使用されている場合は、この方法では移行できません。
(上述の補足事項を記載する)
・PL/SQL の RECORD 型は幾つかの関連性を持つデータ項目をまとめて、1 つの型として扱うことを
可能にしています。
DB2Java では必要なデータ項目をマッピングしたクラスを作成し、RECORD 型を扱う個所と置
き換えることにより移行します。
(本ガイドで自作クラスを使用した移行は対象外)
・PL/SQL の RECORD 型が入出力引数に使用されている場合は、DB2Java で指定可能なデータ型に自
作クラスが含まれないため移行不能です。
移行可能な PL/SQL の入出力引数は、本ガイドの「4.3 PL/SQL,DB2Java データタイプマッピ
ング」を参照してください。
IBM Software Group
2−11
(4) TABLE 型
PL/SQL の TABLE 型については、静的一次元配列に移行することが最も簡単な DB2Java への移行方
法ですが、インデックス初期値が「0」となる点に注意が必要です。
⇒以下はサンプルコード 3 より抜粋したコードです。
PL/SQL
TYPE TYPE_TABLE IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
W_RANK TYPE_TABLE;
BEGIN
W_RANK(1) := 10;
W_RANK(2) := 100;
W_RANK(3) := 1000;
DB2Java
short w_rank[]
w_rank[0] = 10;
w_rank[1] = 100;
w_rank[2] = 1000;
if( w_in < w_rank[0] )
IF W_IN < W_RANK(1) THEN
IBM Software Group
= new short[3];
2−12
2.2.3 変数の代入
PL/SQL の変数代入には以下の 2 手段がありますが、DB2Java では等号”=”による変数代入だけで行い
ます。
(1) 直接代入
リテラルおよび変数を直接代入する方式です。
・数値リテラル
PL/SQL、DB2Java の双方で特に違いはありません。
・文字列リテラル
PL/SQL は代入値をシングル・クォートで囲み、DB2Java はダブル・クォートで囲みます。
(2) DML 代入
SELECT 文およびカーソルフェッチ等による DML 構文での代入方式です。
・INTO
DB2Java では対応できません。JDBC による DML 文と同等の SQL ステートメント発行を行い、結
果セットを直接代入と同様に格納する構造に変更する必要があります。
⇒以下はサンプルコード 2 より抜粋したコードです。
PL/SQL
CREATE PROCEDURE SAMPLE2 IS
X NUMBER
Y NUMBER
BEGIN
X := 0;
Y := X;
SELECT MAX(EMPNO) INTO
END;
(1)直接代入
Y FROM EMP
(2)DML 代入
IBM Software Group
DB2Java
public class Sample2
{
private static short X
private static short Y
public static void sample2(
)
{
X = 0;
Y = X;
Y = ResultSetの取得メソッド等();
}
}
2−13
(3) カーソル属性代入
以下に示すカーソル属性はいずれも PL/SQL のカーソルに関連するカーソル属性をシステムより
取得するためのものです。カーソルの移行については本ガイドの「2.2.6 カーソル処理」にて述
べていますので、そちらをご参照ください。
・レコードに関連する情報を収めたカーソル属性(%ROWCOUNT)
DB2Java に単純移行することはできません。
PL/SQL では一般的となっている、データベースのシステムによる情報の自動更新に依存した構
造は、DB2Java においては、通常の変数を使用して同等の情報が取得可能な処理構造に置き換
える必要があります。以下は、%ROWCOUNT に関する例です。%ROWCOUNT は現時点までに取り出し
た行数を返します。また、カーソルまたはカーソル変数をオープンした状態では 0 を返します。
これを考慮すれば次のようなロジックで%ROWCOUNT の機能を代替することができます。
1. %ROWCOUNT 用の変数を宣言し、0 で初期化
2. 行を取り出すたびに変数をインクリメント
⇒以下はコード例です。(例では、あるカーソルから行を取り出し、10 行を超えたらループを
抜け出すようになっています。)
PL/SQL
LOOP
FETCH c1 into …
IF c1%ROWCOUNT > 10 THEN
EXIT;
END IF;
END LOOP;
DB2Java
short rowcount = 0;
rs = stmt.executeQuery()
while (rs.next())
{
rowcount += 1;
if( rowcount > 10 )
{
break;
}
}
・レコードに関連するステータス情報を収めたカーソル属性(%FOUND、%NOTFOUND)
SQLException を発生させずに例外情報を取得することが可能な、DB2Java のメソッドを使用して
取得する構造に置き換える必要があります。
⇒以下はコード例です。(以下は%NOTFOUND の例です。)
PL/SQL
FETCH c1 into …
IF c1%NOTFOUND THEN
…
END IF;
カーソル「c1」の特殊属性「NOTFOUND」は
システムが自動取得しています
IBM Software Group
DB2Java
if(
{
2−14
!rs.next()
)
…
}
カーソル「c1」に相当する結果セットを
取得する際の戻り値が、「%NOTFOUND」と
同等の判定として使用できます。
・カーソルの異常処理情報を収めたカーソル属性(%ISOPEN)
“%ISOPEN”は SQLException の発生に関連するカーソル解放の要否判断等に使用するカーソル属
性ですが、DB2Java に単純移行が可能な属性は用意されていません。
同等の判断処理に構造に置き換える必要があります。
⇒以下はコード例です。
PL/SQL
IF
c1%ISOPEN
CLOSE c1;
END IF;
THEN
DB2Java
if(
{
rs.close();
}
IBM Software Group
rs != null
2−15
)
2.2.4 条件分岐
PL/SQL の条件分岐(IF∼ELSE)は DB2Java でも同様の構文が用意されています。
構文の記述に若干の相違点があります。
(1) 比較 1
DB2Java では、条件内容や条件該当時の処理内容を括弧で括る必要があります。
条件内容に文字列を使用することも同様に可能ですが、リテラルとの直接比較はできません。
文字列オブジェクトの比較用メソッドを使用して比較します。
(2) 比較 2
比較を継続する記述「ELSIF」は DB2Java では「else if」と記述します。
条件内容に等号や不等号を記述することは、DB2Java でも同様に利用が可能です。
(3) 比較 3
PL/SQL、DB2Java の双方で特に違いはありません。
(4) 終端
終端を明記する「end if;」は DB2Java では不要です。
⇒以下はサンプルコード 1 より抜粋したコードです。
PL/SQL
CREATE PROCEDURE SAMPLE1
IS
引数
BEGIN
<<SUB2>>
DECLARE
W_SUB_VAL NUMBER;
W_STRING VARCHAR2(1);
BEGIN
W_STRING := TO_CHAR(W_IN);
IF W_STRING = '0' THEN
(1)比較 1
W_CAL := 0;
ELSIF W_STRING > '5' THEN
(2)比較 2
W_SUB_VAL := 100;
W_CAL := W_CAL + W_SUB_VAL;
ELSE
W_SUB_VAL := 200;
W_CAL := W_CAL + W_SUB_VAL;
END IF;
GOTO SUB2_RETURN;
(3)比較 3
END;
(4)終端
END SAMPLE1;
IBM Software Group
DB2Java
public class Sample1
{
public static void sample1(引数)
{
処理内容(メイン)
Sub2();
}
private static void sub2()
{
short w_sub_val = 0;
String w_string = String.valueOf(w_i);
if( w_string.compareTo("0") == 0 )
{
w_cal = 0;
}
else if( w_string.compareTo("5") > 0 )
{
w_sub_val = 100;
w_cal = (short)(w_cal + w_sub_val);
}
else
{
w_sub_val = 200;
w_cal = (short)(w_cal + w_sub_val);
}
}
}
2−16
2.2.5 反復制御
PL/SQL の反復制御(ループ)は DB2Java でも同様の構文が用意されています。
構文の記述に若干の相違点があります。
(1) 反復する範囲の移行
PL/SQL では「LOOP」∼「end LOOP」間が反復範囲です。
DB2Java は「while 構文に囲まれた処理ブロック」が反復範囲となります。
(2) 反復を継続する条件の移行
PL/SQL、DB2Java の双方で特に違いはありません。
(3) 反復を中断する条件の移行
反復を継続する条件(2)以外で反復終了(カーソルの終端到達)の判断を必要とする条件です。
PL/SQL では「NOTFOUND」等の特殊な属性に依存した構造も見られます。
DB2Java では「ResultSet」インターフェースの「next」メソッドの戻り値を判定する必要があり
ます。
⇒以下はサンプルコード 2 より抜粋したコードです。
PL/SQL
W_CNT NUMBER;
(2)継続する条件
BEGIN
W_CNT := 0;
WHILE W_CNT < 10 LOOP
(3)中断する
FETCH c1 INTO W_SAL;
条件
EXIT WHEN c1%NOTFOUND;
W_CNT := W_CNT + 1;
END LOOP;
IBM Software Group
(1)反復する
範囲
DB2Java
short w_cnt = 0;
while( w_cnt < 10 )
{
if( rs.next() == false )
{
break;
}
w_sal[0] = rs.getShort(1);
w_cnt++;
}
2−17
(2)
(3)
(4) カーソル FOR ループの移行
PL/SQL のカーソル FOR ループ構文では、暗黙的に反復する条件が「反復終了まで継続」に定義さ
れ、それらに関連する判定や変数も同様に暗黙的に定義されます。
DB2Java 移行では、それらの移行に関して反復を継続/終了する条件判定の組み合わせを再検討
し、関連する変数等を含めて明示的に移行する必要があります。
⇒以下はサンプルコード 2 を同等のカーソル FOR ループ構文に置き換えたコード例です。
PL/SQL
W_CNT NUMBER;
BEGIN
W_CNT := 0;
FOR c1_rec IN c1 LOOP
W_SAL := c1_rec.sal;
W_CNT := W_CNT + 1;
EXIT WHEN W_CNT > 10;
END LOOP;
IBM Software Group
DB2Java
short w_cnt = 0;
while( rs.next() == false )
{
if( w_cnt < 10 )
{
break;
}
w_sal[0] = rs.getShort(1);
w_cnt++;
}
2−18
2.2.6 カーソル処理
PL/SQL のカーソル処理を移行する場合には、DB2Java では結果セット(ResultSet)を使用する構造
に移行します。カーソル処理の構文記述を宣言、開始、取得、終了の各段階毎に移行方法を記載し
ます。
(1) 宣言「CURSOR」
移行元の PL/SQL ではカーソルの宣言は独立した単独の定義でしたが、DB2Java ではカーソル宣言
を SQL 文の定義、SQL 文を書き込むコンテキストの定義、照会結果を格納する変数の定義等の要
素に分けて考慮し、移行します。
①カーソル変数の移行
PL/SQL のカーソル変数の宣言は、DB2Java では結果セットのインスタンスに移行します。
②SQL 文の宣言の移行
PL/SQL のカーソルを抽出する条件(SQL 文)の宣言は、DB2Java ではデータベースとの接続イン
ターフェース「Connection」のコンテキストに条件(SQL 文)を定義する構造に移行します。
(以下はカーソルの宣言の SQL にパラメーターが使用されている場合に必要です)
③SQL 文のパラメーターの移行
DB2Java では接続インターフェースのコンテキストに定義する SQL 文の IN パラメーター・プレ
ース・ホルダー「?」に移行します。
④プレースホルダーに値をセットする処理の追加
IN パラメーター・プレース・ホルダーはインターフェース「PreparedStatement」
のメソッドを使用して設定する構造に移行します。なお、IN パラメーターの定義された SQL 型
と互換のあるメソッドを使用しなければならないことにご注意ください。
(例えば、IN パラメーターが Integer 型ならば setInt メソッドに移行します。)
⇒以下はサンプルコード 2 より抜粋したコードです。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE2(
W_IN_NO IN EMP.EMPNO%TYPE,
) AS
①
CURSOR c1 IS
DB2Java
public static void sample2(
short w_in_no
)
ResultSet rs = null;
SELECT sal FROM emp WHERE empno > W_IN_NO;
③ PreparedStatement stmt = null;
String sql =
BEGIN
"SELECT SAL FROM EMPLOYEE WHERE EMPNO > ?";
②
stmt = con.prepareStatement( sql );
④
stmt.setShort( 1, w_in_no );
IBM Software Group
2−19
(3) オープン(OPEN)とクローズ(CLOSE)
①カーソルのオープンの移行
PL/SQL のカーソルのオープン(OPEN)は、DB2Java ではデータベースとの接続インターフェース
「Connection」の SQL 実行と結果取得を行うメソッド「createStatement」を実行する構造に移
行し、暗黙的にカーソルをオープンします。
(データベースとの接続インターフェースに関しては前項(1)を参照)
②「①」でカーソルの宣言の SQL に変数が使用されている場合
SQL 実行と結果取得を行うメソッドには「prepareStatement」を使用します。その他の部分は、
①と同様に移行します。
③カーソルのクローズの移行
PL/SQL のカーソルクローズ(CLOSE)は、DB2Java ではカーソルのオープンに使用したインターフ
ェースを、それぞれのインターフェースが持つクローズメソッド(close)によって解放する構造
に移行します。
解放ではそれぞれのインターフェースが未確保の場合に備えて NULL 確認後に解放を行います。
カーソルのクローズし忘れたことによるメモリ資源の消費には特に注意が必要です。
⇒以下はコード例です。
PL/SQL
BEGIN
OPEN c1;
省略
DB2Java
Connection con =
DriverManager.getConnection(
"jdbc:default:connection" ); (※)
①
CLOSE c1;
ResultSet rs = null;
PreparedStatement stmt = null;
③
stmt
= con.prepareStatement(SQL 文);
rs
= stmt.executeQuery();
省略
②
if( rs != null ) {
rs.close();
}
if( stmt != null ) {
stmt.close();
}
if( con != null ) {
con.close();
}
(※) ストアード・プロシージャーの場合、URL の指定を”jdbc:default:connection”とする必要があ
ります。
IBM Software Group
2−20
(4) 取得「FETCH」
PL/SQL の取得(FETCH)動作は、カーソル行の取得成否を判定する動作、カーソル行の内容を取得
する動作、次カーソル行へ移動する動作の 3 処理を一連動作として実行しますので、DB2Java で
はそれぞれを相当するインターフェースとメソッドを使用する構造に変更する必要があります。
①カーソル行の取得判定にはカーソル変数に対する「next」メソッドの成否で判定します。
②カーソル行の移動は取得判定と同時に「next」メソッドで実施します。
③カーソル行の内容取得には結果セットに対する「getXXX」メソッドを使用します。
取得用メソッドにはカーソル変数の対象項目番号(宣言順に 1∼)を指定して取得します。
(カーソルの 3 番目の項目“数量”を取得する例)
カーソル「cur」
PL/SQL
DB2Java
番号
名称
数量
日付
no
name
sal
date
:= cur.sal
= cur.getShort(3);
3 番目の項目(sal)が Short 型なので、
メソッド「getShort」を使用します。
その他の型の場合には別途対応したメソッドを
使用する必要があります。
⇒以下はサンプルコード 2 より抜粋したコードです。
PL/SQL
BEGIN
FETCH c1 INTO W_SAL;
DB2Java
ResultSet rs = null;
①
rs = stmt.executeQuery();
②
if(
{
rs.next()
)
w_sal[0] = rs.getBigDecimal(1);
③
IBM Software Group
}
2−21
2.2.7 例外処理
PL/SQL の例外処理は DB2Java でも同様の構文が用意されています。
構文の記述に若干の相違点があります。
代表的な以下 3 種類の例外について記載します。
①ユーザーが RAISE する例外
②システムが発生させる例外
③その他の全ての例外(Exception)
・注意点
移行後の DB2Java の構造には、Exception のエラーメッセージ取得処理とエラーメッセージの判
別を行う処理を加える必要があります。
以下の抜粋コードを例とした場合、①と②の切り分けに Exception のメッセージ取得とスローさ
れたメッセージの判定が加えられた構造に該当します。
④データベースアクセスエラーに関する情報を提供する例外(SQLException)
その他の全ての例外(Exception)のサブクラスに、データベースアクセスエラーに関する情報を
提供する例外(SQLException)がありますが、その他の全ての例外とほぼ同様の移行手順となる
ため本ガイドでは記載していません。
・注意点
SQLException では例外の情報をエラーコードから取得します。
次頁にサンプルコード 4 より抜粋したコードを記載します。
IBM Software Group
2−22
⇒以下はサンプルコード 4 より抜粋したコードです。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE4(
W_IN1 IN NUMBER,
W_IN2 IN NUMBER,
W_OUT1 OUT NUMBER,
) AS
BEGIN
W_OUT1 := W_IN1 / W_IN2;
IF W_OUT1 > 9999 THEN
RAISE user_over;
END IF;
EXCEPTION
①WHEN user_over THEN
W_OUT1 := 9999;
②WHEN ZERO_DIVIDE THEN
W_OUT1 := 1;
WHEN
OTHER THEN
③
W_OUT1 := 0;
END SAMPLE4;
IBM Software Group
DB2Java
public class Sample4
{
public static void sample4(
short w_in1,
short w_in2,
short w_out1[]
)
throws Exception{
try {
if( w_out1 > 9999 ) then
{
throw new Exception("user_over");
}
w_out1 = w_in1 / w_in2;
③ } catch (Exception e) {
String errm = e.getMessage();
if( errm.compareTo("user_over") == 0 )
{
w_out1 = 9999;
}
else
①
{
w_out1 = 0;
}
② } catch (ArithmeticException ae) {
w_out1 = 1;
}
}
2−23
2.3
考慮点
DB2Java では PL/SQL の機能をそのまま移行できない場合があります。以下示しているケースは、本ガ
イドの「2.3 移行フロー」でも触れた通り、考慮が必要なケースの一部です。また、対応方法が一概
に言えないものについては割愛させていただいていますし、対応方法の例を載せているケースでも、
実際の移行ではそのまま使えないケースもあります。移行方法にあたっては一つ一つ検討する必要が
あります。
2.3.1 戻り値を返す場合
DB2Java では、プロシージャーに対応するメソッドを public static void で定義する必要がありま
す。これは DB2Java では戻り値を返せないことを意味しています。PL/SQL で戻り値を返すようなプ
ロシージャーを移行するには次の例に示すような方法が考えられます。
例)戻り値で返していた値を、出力パラメーターで返す
ただしこの方法ではプロシージャーのインターフェースが変更されてしまうため、呼び出し側の
アプリケーションの変更も必要になります。
2.3.2 出力パラメーターにレコード型等の複合情報配列が含まれる場合
DB2Java ではパラメーターに複合情報配列を使用することはできません。対応については、その要
件を把握し、個別に検討するしかありません。
ひとつの移行方法の例として、配列の内容を個別のパラメーターとする方法があります。
例えば次のようなインターフェースを持つプロシージャーがあるとします。
SP(InPar1, OutPar1)
この時、出力変数 OurPar1 は配列でなおかつ、要素は5個に限定されているとします。
その際 DB2Java
では以下のように定義します。
SP(InPar1, OutPar1, OutPar2, OutPar3, OutPar4, OutPar5)
2.3.3
Oracle 組み込み関数、Oracle パッケージを使用している場合
Oracle パッケージの機能はそのまま DB2Java に利用する環境はありません。移行するにあたっては
個別にその方法を検討する必要があります。
Oracle 組み込み関数に関しても基本的には個別に移行方法を検討する必要がありますが、「他社 DB
関数移行用 UDF サンプル」が IBM の Web サイト(以下に示す URL)にて公開されています。そちらを
利用する方法もあります。
http://www-6.ibm.com/jp/software/data/download/udfsample.html
2.3.4 ストアード・プロシージャーをネストしている場合
DB2Java ではストアード・プロシージャーからストアード・プロシージャーをコールすることはで
きません。しかし、コールされる側のストアード・プロシージャーのロジックを新たに Java クラス
IBM Software Group
2−24
(※)に移行することによって、そのクラスのメソッドを呼び出すことができます。
(※)ストアード・プロシージャー向けの Java クラスではなく、汎用的な Java クラスを指していま
す。
2.3.5 ロックに対する考慮
ロックは、複数のトランザクションが並行に処理される場合に、データの一貫性を保証するために
獲得されます。通常、設定に基づき暗黙的に獲得されます。Oracle ではロールバック・セグメント
により読み取り一貫性を提供し、Select 時にはロックを獲得しません。それに対して、DB2 UDB で
は Select 時にもロックを獲得します。Oracle、DB2 UDB のロックの獲得方法についてはそれぞれの
マニュアルを参照してください。
したがって、Oracle が Select 時にロックをかけないことを利用したストアード・プロシージャー
の移行にあたっては、特に注意が必要です。
IBM Software Group
2−25
3.サンプル
本ガイドの「2.2 基本的な PL/SQL 構文から Java への構文比較」に使用したサンプル・プログラムお
よびサンプル・プログラムを稼動させるための環境構築の方法を記載します。
3.1
サンプル・プログラムのリスト
本ガイドで紹介しているサンプル・プログラムのリストです。
サンプル
PL/SQL ファイル名
Sample1.sql.sql
Java ファイル名
プロシージャー作成ファイル名
Sample1.java
Sample1.bld
サンプルコード 1
Sample1.sql
Sample1.java
Sample2.sql
Sample2B.sql
Sample1.bld
Sample2.java
Sample2.bld
サンプルコード 2 (※)
Sample2.sql
Sample2b.sql
Sample3.sql
サンプルコード 3
Sample2.java
Sample2.bld
Sample3.java
Sample3.bld
Sample3.sql
Sample3.java
Sample3.bld
Sample4.java
Sample4.bld
Sample4.sql
サンプルコード 4
Sample4.sql
Sample4.java
Sample4.bld
(※) サンプルコード 2 の実行にあたっては、「2.1 移行フロー」の(※2)に示した JDBC2.0 を利用する
際の設定が必要となります。
IBM Software Group
3−1
3.2
サンプル・プログラムを稼動させるための環境構築方法
Oracle、DB2 UDB ともに、テーブルの作成、ストアード・プロシージャーの作成をする必要がありま
す。
3.2.1 DB2 UDB の環境構築方法
・テーブル作成方法
DB2 UDB ではサーバー導入時に SAMPLE データベースを作成することができます。そこで作成されて
いれば、そのまま使用できます。(EMPLOYEE 表のみ必要です。)なんらかの理由により、SAMPLE デー
タベースを作成しなかったり、テーブルが利用できなかった際は添付の Create_Employee.db2 を利
用し以下のコマンドにより作成できます。
> db2 ‐ tvf Create_Employee.db2 <Enter>
Create_Employee.db2
・ストアード・プロシージャー作成方法
本ガイドの「2.1.1 SPB を使用する移行手順」あるいは「2.1.2 SPB を使用しない移行手順」を参照
してください。
3.2.2
Oracle の環境構築方法
・テーブル作成方法
以下のファイルはテーブル作成用のスクリプト・ファイルです。このファイルを以下のように指定
することでテーブルを作成できます。(斜字体は環境に依存します。)
> sqlplus username/password@Create_Employee.sql <Enter>
Create_Employee.sql
・ストアード・プロシージャー作成方法
以下のようなコマンドで作成できます。(斜字体は環境に依存します。
)
> sqlplus username/[email protected] <Enter>
IBM Software Group
3−2
3.3
サンプルコード 1
ブロック構造のサンプル・プログラムです。
ここでは、データベース操作は行っていません。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE1(
W_IN IN NUMBER,
W_OUT OUT NUMBER
) AS
W_CAL NUMBER;
BEGIN
W_CAL := 0;
W_CAL := W_CAL + W_IN;
GOTO SUB1;
<<SUB1_RETURN>>
GOTO SUB2;
<<SUB2_RETURN>>
GOTO MAIN_END;
DB2Java
public class Sample1
{
private static short w_i = 0;
private static short w_cal = 0;
public static void sample1(
short w_in,
short w_out[]
)
throws Exception
{
w_i = w_in;
w_cal = w_i;
sub1();
sub2();
w_out[0] = w_cal;
}
<<SUB1>>
DECLARE
W_SUB_VAL NUMBER;
BEGIN
W_SUB_VAL := 10;
W_CAL := W_CAL + W_SUB_VAL;
GOTO SUB1_RETURN;
END;
private static void sub1()
{
short w_sub_val = 0;
w_sub_val = 10;
w_cal = (short)(w_cal + w_sub_val);
}
<<SUB2>>
DECLARE
W_SUB_VAL NUMBER;
W_STRING VARCHAR2(1);
BEGIN
W_STRING := TO_CHAR(W_IN);
IF W_STRING = '0' THEN
W_CAL := 0;
ELSIF W_STRING > '5' THEN
W_SUB_VAL := 100;
W_CAL := W_CAL + W_SUB_VAL;
ELSE
W_SUB_VAL := 200;
W_CAL := W_CAL + W_SUB_VAL;
END IF;
GOTO SUB2_RETURN;
END;
private static void sub2()
{
short w_sub_val = 0;
String w_string = String.valueOf(w_i);
if( w_string.compareTo("0") == 0 )
{
w_cal = 0;
}
else if( w_string.compareTo("5") > 0 )
{
w_sub_val = 100;
w_cal =
(short)(w_cal + w_sub_val);
}
else
{
w_sub_val = 200;
w_cal =
(short)(w_cal + w_sub_val);
}
}
<<MAIN_END>>
W_OUT := W_CAL;
END SAMPLE1;
/
}
IBM Software Group
3−3
サンプルコード 1「Create Procedure」コマンド
プロシージャー名
パラメータ名、パラメータのデータ型
結果セットのパラメータ指定(0: 未使用)
SQL データの参照および更新なし
同一パラメータでも都度実行を行う
パラメータに NULL 値を認める
プロシージャーJava のメソッドに指定
パラメータの形式を Java に指定
クラス識別子とメソッド識別子
create procedure sample1
(in w_in smallint, out w_out smallint)
dynamic result sets 0
contains sql
not deterministic
called on null input
language java
parameter style java
external name'Sample1.sample1'
;
IBM Software Group
3−4
3.4
サンプルコード 2
カーソルとループ構造のサンプル・プログラムです。
「EMPLOYEE」表を検索に使用します。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE2(
W_IN_NO IN EMPLOYEE.EMPNO%TYPE,
W_SAL OUT EMPLOYEE.SALARY%TYPE,
W_OUT OUT NUMBER
) AS
CURSOR c1 IS SELECT salary FROM employee
WHERE empno > W_IN_NO;
W_CNT NUMBER;
BEGIN
OPEN c1;
W_SAL := 0;
W_CNT := 0;
WHILE W_CNT < 10 LOOP
FETCH c1 INTO W_SAL;
EXIT WHEN c1%NOTFOUND;
W_CNT := W_CNT + 1;
END LOOP;
CLOSE c1;
W_OUT := W_CNT;
END SAMPLE2;
/
DB2Java
import java.sql.*;
import java.math.BigDecimal;
public class Sample2
{
public static void sample2(
String w_in_no,
BigDecimal w_sal[],
short w_out[]
)
throws SQLException, Exception {
w_sal[0] = new BigDecimal(0.);
Connection con =
DriverManager.getConnection(
"jdbc:default:connection"
);
ResultSet rs = null;
PreparedStatement stmt = null;
String sql =
"SELECT SALARY FROM EMPLOYEE WHERE
EMPNO > ?";
stmt = con.prepareStatement( sql );
stmt.setString( 1, w_in_no );
rs
= stmt.executeQuery();
short w_cnt = 0;
while( w_cnt < 10 ) {
if( rs.next() ) {
w_sal[0] = rs.getBigDecimal(1);
}
else {
break;
}
w_cnt++;
}
if( rs != null ) {
rs.close();
}
if( stmt != null ) {
stmt.close();
}
if( con != null ) {
con.close();
}
w_out[0] = w_cnt;
SAMPLE2 のカーソル FOR ループ構文版
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE2B(
W_IN_NO IN EMPLOYEE.EMPNO%TYPE,
W_SAL OUT EMPLOYEE.SALARY%TYPE,
W_OUT OUT NUMBER
) AS
CURSOR c1 IS SELECT salary FROM employee
WHERE empno > W_IN_NO;
W_CNT NUMBER;
BEGIN
W_SAL := 0;
W_CNT := 0;
FOR c1_rec IN c1 LOOP
W_SAL := c1_rec.salary;
W_CNT := W_CNT + 1;
EXIT WHEN W_CNT >= 10;
END LOOP;
W_OUT := W_CNT;
END SAMPLE2B;
/
IBM Software Group
}
}
3−5
サンプルコード 2「Create Procedure」コマンド
プロシージャー名
パラメータ名、パラメータのデータ型
create procedure sample2
(in w_in_no varchar(6),
out sal decimal(9,2),
out w_out smallint)
dynamic result sets 0
modifies sql data
not deterministic
called on null input
language java
parameter style java
external name'Sample2.sample2'
;
IBM Software Group
結果セットのパラメータ指定(0: 未使用)
SQL データの参照および更新あり
同一パラメータでも都度実行を行う
パラメータに NULL 値を認める
プロシージャーJava のメソッドに指定
パラメータの形式を Java に指定
クラス識別子とメソッド識別子
3−6
3.5
サンプルコード 3
複合データ型構文のサンプル・プログラムです。
ここでは、データベース操作は行っていません。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE3(
W_IN IN NUMBER,
W_OUT1 OUT NUMBER,
W_OUT2 OUT VARCHAR2
) AS
TYPE TYPE_TABLE IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
W_RANK TYPE_TABLE;
TYPE TYPE_RECORD IS RECORD(
IN_NUM NUMBER,
OUT_CHAR VARCHAR2(4)
);
W_REC TYPE_RECORD;
DB2Java
public class Sample3
{
public static void sample3(
short w_in,
short w_out1[],
String w_out2[]
)
throws Exception
{
short w_rank[]
= new short[3];
short w_in_num[]
= new short[1];
String w_out_str[] = new String[1];
w_rank[0] = 10;
w_rank[1] = 100;
w_rank[2] = 1000;
BEGIN
W_RANK(1) := 10;
W_RANK(2) := 100;
W_RANK(3) := 1000;
w_in_num[0] = w_in;
if( w_in < w_rank[0] )
{
w_out_str[0] = "9<";
}
else if( w_in < w_rank[1] )
{
w_out_str[0] = "99<";
}
else if( w_in < w_rank[2] )
{
w_out_str[0] = "999<";
}
W_REC.IN_NUM := W_IN;
IF W_IN < W_RANK(1) THEN
W_REC.OUT_CHAR := '9<';
ELSIF W_IN < W_RANK(2) THEN
W_REC.OUT_CHAR := '99<';
ELSIF W_IN < W_RANK(3) THEN
W_REC.OUT_CHAR := '999<';
END IF;
W_OUT1 := W_REC.IN_NUM;
W_OUT2 := W_REC.OUT_CHAR;
END SAMPLE3;
/
w_out1[0] = w_in_num[0];
w_out2[0] = w_out_str[0];
}
}
IBM Software Group
3−7
サンプルコード 3「Create Procedure」コマンド
プロシージャー名
パラメータ名、パラメータのデータ型
create procedure sample3
(in w_in smallint,
out w_out1 smallint,
out w_out2 varchar(4000))
dynamic result sets 0
contains sql
not deterministic
called on null input
language java
parameter style java
external name'Sample3.sample3'
結果セットのパラメータ指定(0: 未使用)
SQL データの参照および更新あり
同一パラメータでも都度実行を行う
パラメータに NULL 値を認める
プロシージャーJava のメソッドに指定
パラメータの形式を Java に指定
クラス識別子とメソッド識別子
;
IBM Software Group
3−8
3.6
サンプルコード 4
例外処理のサンプル・プログラムです。
ここでは、データベース操作は行っていません。
ユーザーが RAISE する例外の処理、システムが発生させる例外の処理、その他の全ての例外の処理を
含んでいます。
PL/SQL
CREATE OR REPLACE PROCEDURE SAMPLE4(
W_IN1 IN NUMBER,
W_IN2 IN NUMBER,
W_OUT1 OUT NUMBER
) AS
USER_OVER EXCEPTION;
BEGIN
IF W_IN1 > 9999 THEN
RAISE USER_OVER;
END IF;
W_OUT1 := W_IN1 / W_IN2;
EXCEPTION
WHEN USER_OVER THEN
W_OUT1 := 9999;
WHEN ZERO_DIVIDE THEN
W_OUT1 := 1;
WHEN OTHERS THEN
W_OUT1 := 0;
END SAMPLE4;
/
IBM Software Group
DB2Java
public class Sample4
{
public static void sample4(
short w_in1,
short w_in2,
short w_out1[]
)
throws Exception{
try {
if( w_in1 > 9999 )
{
throw new Exception("user_over");
}
w_out1[0] = (short)(w_in1 / w_in2);
} catch (ArithmeticException ae) {
w_out1[0] = 1;
} catch (Exception e) {
String errm = e.getMessage();
if( errm.compareTo("user_over") == 0 )
{
w_out1[0] = 9999;
}
else
{
w_out1[0] = 0;
}
}
}
}
3−9
サンプルコード 4「Create Procedure」コマンド
プロシージャー名
パラメータ名、パラメータのデータ型
create procedure sample4
(in w_in1 smallint,
in w_in2 smallint,
out w_out1 smallint)
dynamic result sets 0
contains sql
not deterministic
called on null input
language java
parameter style java
external name'Sample4.sample4'
結果セットのパラメータ指定(0: 未使用)SQL
データの参照および更新あり
同一パラメータでも都度実行を行う
パラメータに NULL 値を認める
プロシージャーJava のメソッドに指定
パラメータの形式を Java に指定
クラス識別子とメソッド識別子
;
IBM Software Group
3−10
4.付録
プロシージャー移行に関与するツール、及びコマンド等について記載しています。
4.1
SPB「Java ストアード・プロシージャー作成ウィザード」による作成手順
(1) ウィザードの起動
・ストアード・プロシージャー作成先の DB2 UDB に接続されている必要があります。
・SPB「プロジェクト」ログイン時に指定したユーザ(=スキーマ)が継承されます。
IBM Software Group
4−1
(2) 作成するプロシージャーのソース・ファイル名の指定
IBM Software Group
4−2
(3) 作成するプロシージャーのエントリー・ポイントの指定
・複数のメソッドを選択した場合もエントリー・ポイントは一箇所となります。
・SPB を使用したオーバーロード形式のプロシージャー作成は出来ません。
(4) 作成するプロシージャーの名称の指定
・名称は「スキーマ名」
.「プロシージャー名」の形式で指定します。
IBM Software Group
4−3
(5) 作成するプロシージャーのパラメーターの指定
・SPB が提示するパラメーター設定をそのままの形式で指定します。
(6) 「終了」を押下してプロシージャーの作成
・特別名、JarID にはプロシージャー名に則した指定をします。
IBM Software Group
4−4
4.2 PL/SQL の登録内容参照および実行確認に関するコマンド例
(1) 移行する対象の PL/SQL の処理内容を、登録されているデータベースから取得する方法
以下の方法により、移行元 PL/SQL の DDL ファイル等が存在しない場合でも、登録された
データベースよりコード内容を取得できます。
・SQL*Plus によるプロシージャー名の検索
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
に接続されました。
SQL> SELECT OBJECT_NAME FROM USER_OBJECTS WHERE OBJECT_TYPE='PROCEDURE';
OBJECT_NAME
-------------------------------------------------------------------------------SAMPLE1
SAMPLE2
SAMPLE3
SAMPLE4
・SQL*Plus によるプロシージャーの内容表示
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
に接続されました。
SQL> SELECT TEXT FROM USER_SOURCE WHERE NAME='SAMPLE3';
TEXT
-------------------------------------------------------------------------------PROCEDURE SAMPLE3(
W_IN IN NUMBER,
W_OUT1 OUT NUMBER,
W_OUT2 OUT VARCHAR2
) AS
TYPE TYPE_TABLE IS TABLE OF NUMBER
INDEX BY BINARY_INTEGER;
W_RANK TYPE_TABLE;
TYPE TYPE_RECORD IS RECORD(
IN_NUM NUMBER,
OUT_CHAR VARCHAR2(4)
);
W_REC TYPE_RECORD;
BEGIN
W_RANK(1) := 10;
W_RANK(2) := 100;
W_RANK(3) := 1000;
IBM Software Group
4−5
(2) 移行する対象の PL/SQL の動作を、登録されているデータベースで確認する方法
プロシージャーを実行後の出力変数と使用して動作確認を行います。
・SQL*Plus による出力変数の設定
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
に接続されました。
SQL> VARIABLE P2 NUMBER;
SQL> VARIABLE P3 VARCHAR2(100);
SQL>
・SQL*Plus によるプロシージャーの実行
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
に接続されました。
SQL> EXEC SAMPLE3( 1, :P2, :P3 );
・SQL*Plus によるプロシージャーの強制終了
Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production
に接続されました。
SQL> EXEC SAMPLE3( 1, :P2, :P3 );
← 無限ループ発生等
(SYSDBA 権限でログインした SQL*Plus)
SQL> SELECT SID, SERIAL#, USERNAME FROM V$SESSION;
SID
SERIAL# USERNAME
---------- ---------- -----------------------------1
1 SYSTEM
2
1 DBSNMP
11
19 #####
← 「####」は強制終了する
プロシージャーのユーザ名
← ユーザ名から強制終了に用いる
SID と SIRIAL を取得
3 行が選択されました。
SQL> ALTER SYSTEM KILL SESSION '11,19'; ← SID、SIRIAL を指定して強制終了
システムが変更されました。
*
1 行でエラーが発生しました。
ORA-00028: セッションは強制終了されました。
IBM Software Group
4−6
← 強制終了
4.3 PL/SQL,DB2Java データタイプマッピング
数値
Oracle
DB2
DB2 Java
データ型
値範囲
バイト
データ型
値範囲
NUMBER(p,0)
1<=p<=38
最大 21
SMALLINT
INT
BIGINT
NUMBER(p,s)
1<=p<=38
最大 21
DEC(p,s)
-32768 ∼32767
-2147483648∼2147483647
-9223372036854775808
∼ 9223372036854775807
-1031 ∼ 1031-1
NUMBER
38桁精度
最大 21
REAL
DOUBLE
整数
データ型
バイト
2 short
4 int
8 long
(p/2)+1
ゼロ、または
1.175E-37∼3.402E+38、
または
-3.402E+38∼-1.75E-37
ゼロ、または
1.79769E+308∼2.225E-307、
または
-2.225E-308∼-1.797669+308
8 double
データ型
CHAR(n)
NCHAR(n)
VARCHAR2(n)
NVARCHAR2(n)
値範囲
バイト
1 ∼ 2000
n
1 ∼ 4000
実際長
LONG
1 ∼ 2GB
実際長
RAW(n)
1∼ 2000
n
LONG RAW
1 ∼ 2GB
実際長
java.math.BigDecimal
4 float
データ型
NUMBER(1,0) ∼ (NUMBER4.0)
SMALLINT
NUMBER(5,0) ∼ (NUMBER9,0)
INT
NUMBER(10,0) ∼ (NUMBER19,0)
BIGINT
NUMBER(20,0) ∼ (NUMBER38,0)
DOUBLE
桁の切り上げ方がOracleとDB2では異なるので注意が必要です。
OracleのNUMBER(p,0)に、3.4を挿入すると、3となり、3.5を挿入すると、4となりますが(四捨五入)、DB2の整数
(SMALLINT、INTEGER、BIGINT,DECIMAL(p,0))の場合全て3(切り捨て)になります。
文字/バイナリー
Oracle
データ型
データ型
short
int
long
double
DB2
データ型
値範囲
バイト
データ型
VARCHAR(n) ※1
1 ∼ 32672
実際長
String
VARCHAR(n)
(CHAR(n))
CLOB ※2
1 ∼ 32672
1 ∼ 2GB
実際長
実際長
VARCHAR(n) ※3
FOR BIT DATA
BLOB
1 ∼ 32672
1 ∼ 2GB
実際長
実際長
DB2 Java
String
String
String(JDBC1.22)
java.sql.Clob(JDBC2.0)
Byte[]
Byte[](JDBC1.22)
java.sql.Clob(JDBC2.0)
※1 1<=n<=254であればDB2のCHAR(n)も対応できます。
※2 長さによってはDB2のLONG VARCHARやVARCHARで対応出来ます。
※3 1<=n<=254であればDB2のCHAR(n) FOR BIT DATAも対応できます。
LOB
Oracle
データ型
値範囲
バイト
DB2
データ型
値範囲
バイト
データ型
BLOB
4GBまで
実際長
BLOB(n)
2GBまで
実際長
CLOB
4GBまで
実際長
CLOB(n)
2GBまで
実際長
NCLOB
4GBまで
実際長
CLOB(n)
2GBまで
実際長
Byte[](JDBC1.22)
java.sql.Clob(JDBC2.0)
String(JDBC1.22)
java.sql.Clob(JDBC2.0)
String(JDBC1.22)
java.sql.Clob(JDBC2.0)
String(JDBC1.22)
java.sql.Clob(JDBC2.0)
Byte[](JDBC1.22)
java.sql.Clob(JDBC2.0)
DB2 Java
DBCLOB(n)
実際長
BFILE
4GBまで
実際長
BLOB(n)
2GBまで
実際長
日付・時間
Oracle
データ型
値範囲
バイト
DB2
データ型
値範囲
バイト
DATE
BC4712/01/01
∼4712/12/31
(年/月/日/時/分/秒)
7 DATE
TIME
TIMESTAMP
DB2 Java
0001/01/01∼9999/12/13
(年/月/日)
00h00m00s∼24m00m00s
(時/分/秒)
0000/01/01∼9999/12/31
(年/月/日/時/分/秒)
日付のみならDB2のDATE、時間のみならDB2のTIMEが使えます。
OracleからDB2 UDBへデータを移行する際には、フォーマットの変換が必要です。Oracleの関数to_charを用います。
DB2のTIMESTAMPデータタイプへの変換は、to_char(a_date, 'YYYY-MM-DD-HH24.MI.SS')
DB2のDATE データタイプへの変換は、to_char(a_date, 'MM/DD/YYYY')
DB2のTIME データタイプへの変換は、to_char(a_date, 'HH24:MI:SS')
IBM Software Group
4−7
データ型
4 java.sql.Date
3 java.sql.Time
10 java.sql.Timestamp
Fly UP