Oracle から PostgreSQL へのデータ移行? ~異なる DB 間でデータ転送~

データパイプライン

データベース間でデータを転送したいケースは多々あると思います。 たとえばシステム移行、他システムへの連携、バックアップからの復元・・・などなど。 同じ DBMS 同士での転送なら楽かもしれませんが、異なる DBMS ともなると、これがひと苦労ですよね。

また、転送する目的によってケースもさまざまです。 移行のためテーブルを新たに作成するのか、転送元のデータを加工した二次データを既存のテーブルに更新するのか・・・。 転送先にキーが重複するデータがある場合はどうしよう? 既存データを保持するか、それとも上書きするか?

そんな悩みを解決するのが、今回ご紹介する PowerBuilder のデータパイプラインという機能です。 データベース間のデータ転送を簡単に実現します。

※本稿は Oracle DB から PostgreSQL への移行を推奨する記事ではありません。


データパイプラインの概要

データパイプラインは、「ある DB から別の DB へデータを転送」するための、その名の通り「データのパイプライン」としての機能を果たします。 同一のデータベースはもとより、異なる DBMS 間でも転送できるスゴイやつです。

そして、もう一つのパイプラインのキモが、転送先 DB に転送するデータは SELECT 文で指定できるところです。 つまりテーブルを丸ごと転送するだけにとどまらず、「データの加工」や転送元のデータを基にして「全く新しいテーブルを作る」ことだって、ひとつの操作でできるということです。

転送元に一時テーブルやビューを作ることなく、”INSERT … SELECT” のイメージで異なる DBMS にテーブル作成からデータ挿入までできちゃうんですね。 便利すぎ!

しかも、データウィンドウと同じく SELECT 文の作成は簡単なものならマウス操作のみで行うことも可能なんです。


Pipeline の作成

さて早速ですが、実例として Oracle DB から PostgreSQL へ同一のテーブルを作成しデータの転送をしてみましょう。 なお、データ転送に対応しているデータベースは PowerBuilder がサポートしているデータベースです。 あらかじめ「DB プロファイル」で転送元/転送先に接続できるプロファイルを作成しておいてください。

まず、メニュー [ファイル | 新規作成] で新規作成ダイアログを開き、[データベース] タブを開いてみましょう。 その中に「データ パイプライン」がありますね。 これを選択し [OK] ボタンをクリックします。

新規作成

次の画面では転送元と転送先の DB プロファイルを設定します。 データウィンドウと同様にデータソースとして “Quick Select”、 “SQL Select”、 “クエリ”、 “ストアド プロシージャ” から選択できます。

DB の指定では DB プロファイルを選択します。 DB インターフェイスをまたいで PowerBuilder IDE に登録されているすべての DB プロファイルが表示されています。 プロファイル名しか表示されないので、わかりやすく命名されていないと探すのがひと苦労ですね。 今回は転送元に Oracle DB、転送先に PostgreSQL のプロファイルを選択し “SQL Select” 形式で作成します。

DBプロファイル選択

つづいて転送元のテーブルとカラムを選択します。 作成方法はデータウィンドウとまったく同じ。 先ほど選択したデータソースの種類に応じてテーブルなどの指定方法は変わりますが、ここでは “SQL Select” を選択したので、転送したいテーブルを選択します。

今回は単一のテーブルのすべての項目を転送しますが、複数のテーブルを結合した複雑な SELECT 文なども記述することができますよ。

カラム選択

選択できたらツールバーの [ペインタに戻る] ボタンをクリックするか、メニューの [ファイル | データ パイプライン ペインタに戻ります] (変なメニュー名・・・) を選択してペインタ画面に移動します。

それがこちら。

データパイプラインペインタ

パイプラインペインタの説明

ざっと画面を説明していきましょう。

ペインタの説明

「①テーブル名」は転送先に作成される、もしくは更新されるテーブル名。「②キー」は主キーの名称です。

「③オプション」については後述しますが、テーブルの作成 or 更新、上書きする or しない、といった動作が決まる一番大事なオプションです。

「④最大エラー件数」は処理中に発生したエラーを何件まで許容するか。「⑤コミット単位」は複数行のデータを転送する際に何行ごとに COMMIT を行うかを指定することができます。

「⑥拡張属性の移行」は以前ブログで書いた「拡張属性テーブル」の情報を転送元のデータベースから転送するか (転送するテーブル、カラムに関する情報) といったことを指定できます。

「⑦」は転送するカラムの一覧です。転送元のカラム名とデータ型、転送先のカラム名、データ型、NOT NULL 制約やデフォルト値を設定できます。

転送オプション

オプションについての詳細は下記の通り。

オプション 説明
作成 – テーブルの追加 元となるデータベースのテーブルと同じ定義のテーブルを作成し、データもコピーされます。 すでに同じ名前のテーブルがある場合はエラーになります。
置き換え – テーブルの削除/追加 指定したテーブルと同じ名前の既存テーブルを破棄したあと、テーブルを新規作成して転送元テーブルから行を挿入します。 指定した名前のテーブルが存在しなければテーブルが新規作成されます。
リフレッシュ – 行の削除/挿入 既存のテーブル内のデータ行がすべて削除され、転送元テーブルから選択した行が挿入されます。
追加 – 行の挿入 既存のテーブル内のデータがすべて保持され、転送元テーブルから選択した新しい行が挿入されます。
更新 – 行の挿入/更新 転送元テーブルから選択した行データのキーと一致する既存テーブル内の行が更新され、キーと一致しない行は挿入されます。

転送元と転送先のテーブルのデータを定期的に同期させる場合は「リフレッシュ – 行の削除/挿入」。 特定の行のみを更新し、それ以外の既存データはそのままにしたいという場合には「更新 – 行の挿入/更新」を指定するなど、さまざまな用途に対応できるようになっています。


転送の方法

データの転送は、このペインタとスクリプトの両方から行うことができます。 それぞれポイントがあるので詳しく見ていきましょう。

ペインタから実行

ペインタからの実行はツールバーの [パイプラインの実行] ボタン、またはメニューの [デザイン | 実行] から行います。 実行すると即座に転送が行われ、成功した場合は結果が IDE のステータスバーに表示されます。 転送に成功した場合は特にメッセージも出ないので、ここを見逃すと転送が終了したことに気づきにくいので注意!

ステータスバー

わかりにくっ!

エラーが発生した場合はエラー修正画面が表示されます。ここでは発生した DB エラーの一覧からデータの修正を行うことができます。

DBプロファイル選択

作成される転送先テーブルの dept_name のサイズを 5 にしてみました

転送するデータの型が異なる場合や一意制約違反などがあった場合、転送エラーとなったデータをここで直接修正して再度実行することができます。 そもそもテーブルの定義が間違っていた場合はツールバーの [デザイン] ボタンやメニューの [デザイン | デザイン] で前の画面に戻って定義を修正しましょう。

ここでは自動でコミットされるため、これで転送は完了します。 この定義を使ってアプリケーションからスクリプトで使用する場合にはここで保存します。

スクリプトから実行

スクリプトからは Pipeline オブジェクトを利用してデータ転送を行うのですが、下記 2 点の準備が必要になります。

  • トランザクションを 2 つ用意する
  • 画面上にデータウィンドウを配置する

まず 12 つのトランザクションについてですが、これはもちろん「転送元」と「転送先」の DB 接続に使用するものです。 転送を実行する際には、接続済みの 2 つの Transaction オブジェクトを指定します (転送元と転送先の DB が同じ場合は 1 つのトランザクションでも OK です)。

ひとつのアプリケーションで複数の Transaction オブジェクトを使用する方法についてはTips に記事がありますのでこちらもチェック!

そして 2データウィンドウというのは、IDE での実行後にも表示されていた「エラー修正画面」を表示するためのものです。 このデータウィンドウがないとエラーの箇所や内容がわからないし、データを修正して再実行することができません。

内容はエラー発生時に自動で表示してくれるのでデータオブジェクトを指定する必要はなく、空のデータウィンドウコントロールを配置するだけで OK です。

さて、実際にコーディングしていきましょう。 DataStore オブジェクトに使用するデータウィンドウを指定するときと同じように、インスタンス化した Pipeline オブジェクトの DataObject プロパティに作成したデータパイプラインを指定します。

ん~、ちょっとわかりにくいですね。 実際のスクリプトを見てもらった方がいいかも。

pipeline lpip_dept

// Pipeline をインスタンス化
lpip_dept = create pipeline

// ペインタで作成したデータオブジェクト (データパイプライン) を設定
lpip_dept.dataobject = "pip_deparmtment"

DataStore の準備とよく似ていますね。 次にトランザクションを用意しましょう。 下の例では転送元と転送先にそれぞれ別の Transaction オブジェクトを作成しています。 もちろん SQLCA を利用しても構いません。

transaction ltr_from // 転送元トランザクション
transaction ltr_to // 転送先トランザクション

ltr_from = CREATE transaction
ltr_to = CREATE transaction

// 転送元 DB 接続
ltr_from.DBMS = "ORA Oracle"
ltr_from.ServerName = "ORCL"
ltr_from.LogId = "TestUser"
ltr_from.LogPass = "***"

CONNECT USING ltr_from;

// 転送先 DB 接続
ltr_to.DBMS = "ODBC"
ltr_to.DBParm = "ConnectString='DSN=PostgreSQL_sample;UID=testuser;PWD=***'"

CONNECT USING ltr_to;

ここまで準備できたら、あとは転送処理ですね。 転送は Start 関数で行います。

Start の構文

pipelineobject.Start ( sourcetrans, destinationtrans, errorobject {, arg1, arg2,..., argn } )

引数の sourcetrans は転送元、destinationtrans は転送先のトランザクションで、errorobject はエラーの一覧を表示するデータウィンドウコントロール (または DataStore) を指定します。 arg1 ~ argn は転送元のデータソースに使用している検索引数で、データウィンドウの Retreive と同じように定義した検索引数の数だけ指定します。 検索引数が無ければ指定は不要です。

エラーの修正

エラーの処理については IDE と同じです。 エラーが発生した場合には Start 関数で指定したデータウィンドウにエラー内容と転送に失敗したデータが一覧表示されるので、適切にデータを修正した後で Repair 関数を呼び出します。

Repair の構文

pipelineobject.Repair ( destinationtrans )

Repair 関数は Start 関数を呼び出した際に指定したデータウィンドウで行われた修正に対して再実行を行うので、Start を呼び出した Pipeline オブジェクトでなければいけません。 このため、修正を行うことを前提としている場合は Pipeline オブジェクトをインスタンス変数やグローバル変数として宣言する必要があります。

また、Start や Repair の実行中に処理をキャンセルすることもできます。 処理のキャンセルは Cancel 関数で行います。

Cancel の構文

pipelineobject.Cancel ( )

実践

さて、ここまでを踏まえて改めてスクリプトを使ったデータ転送を実践したいと思います。 サンプルでは画面にデータウィンドウ (dw_1) を配置し、エラー修正も行うことを前提としているため、インスタンス変数に宣言した Pipeline オブジェクトと Transaction オブジェクトを使用します。

サンプル画面

また、今回転送する Oracle DB のテーブルはこのようなもの。

DBプロファイル選択

このテーブルのいくつかの項目のみをピックアップした、新しいテーブルを PostgreSQL に作成してみたいと思います。 データパイプラインは下記のように設定しています。 新規で作成するためオプションは「作成 – テーブルの追加」です。

DBプロファイル選択

先頭のいくつかの項目をピックアップしてます

DBプロファイル選択

データパイプラインの定義

インスタンス変数の宣言

pipeline ipip_emp // パイプライン

transaction itr_from // 転送元トランザクション
transaction itr_to // 転送先トランザクション

Pipeline の準備と DB 接続処理 (Openイベントなど)

// Pipeline をインスタンス化
ipip_emp = create pipeline

// データオブジェクトを設定
ipip_emp.dataobject = "pip_employee"

// トランザクションをインスタンス化
itr_from = CREATE transaction // 転送元
itr_to = CREATE transaction // 転送先

// 転送元 DB に接続
itr_from.DBMS = "ORA Oracle"
itr_from.ServerName = "ORCL"
itr_from.LogId = "TestUser"
itr_from.LogPass = "***"

CONNECT USING itr_from;

// 転送先 DB に接続
itr_to.DBMS = "ODBC"
itr_to.DBParm = "ConnectString='DSN=PostgreSQL_sample;UID=testuser;PWD=***'"

CONNECT USING itr_to;

データ転送処理 (ボタンの Clicked イベントなど)

integer li_res

// データ転送 (エラー内容を dw_1 に表示)
li_res = ipip_emp.Start(itr_from, itr_to, dw_1)

IF li_res = 1 THEN
    MessageBox("Pipeline Error", "データの転送に成功しました。")
ELSE
    MessageBox("Pipeline Error", "データの転送に失敗しました。")
END IF

修正後データの転送処理 (ボタンの Clicked イベントなど)

integer li_res

// 修正データ転送
li_res = ipip_emp.Repair(itr_to)

IF li_res = 1 THEN
    MessageBox("Pipeline Error", "修正データの転送に成功しました。")
ELSE
    MessageBox("Pipeline Error", "修正データの転送に失敗しました。")
END IF

転送キャンセル処理 (ボタンの Clicked イベントなど)

integer li_res

// 転送をキャンセル
li_res = ipip_emp.Cancel()

IF li_res = 1 THEN
    MessageBox("Pipeline Error", "データ転送をキャンセルしました。")
ELSE
    MessageBox("Pipeline Error", "データ転送のキャンセルに失敗しました。")
END IF

さぁ、実行結果は・・・?

転送結果

選択した項目のみのテーブルが PostgreSQL に作成され、データも挿入されています。


まとめ

データパイプラインを使うことで、(PowerBuilder に慣れていれば) 特に難しいことなく他の DB にデータを転送することができると思います。

近年、安価で信頼性もあるデータベースもリリースされており、データベースの移行を検討されている方も多いようです。 データ移行の方法は多々あると思いますが、もしお手元に PowerBuilder があるのならデータパイプラインが役に立つんじゃないでしょうか?

ほかにもテーブルの同期や他のシステムへの定期的な転送など、工夫次第で活用できるシチュエーションは山盛りです。 ぜひ、ご検討あれ!

以上、エイタでした!

テクニカルブログ 一覧を見る
PowerBuilder マイグレーション