OracleからPostgreSQLへの移行を見積もると、たいてい最初の想定より大きな数字が返ってきます。テーブルとデータを移すだけなら数日で終わるのに、ストアドプロシージャとトリガとビューを数えた途端に人日が跳ね上がる。移行の難所はデータの移送ではなく、Oracleの方言で書かれたコードをPostgreSQLの文法と挙動へ移し替えるところにあります。
この記事は、Oracleを移行元、PostgreSQLを移行先とする異種移行の実装手順を扱います。互換性の差分、ora2pgによる評価と変換、AWS SCTとDMSを使う構成、テスト設計、移行可否の判断基準までを順に並べました。位置づけはデータベースとは?種類・DBMS・RDBとNoSQLの選び方、移行先の性格はPostgreSQLとMySQLの違いを徹底比較に譲ります。前提はPostgreSQL 18系(2026年8月時点で18.6が最新マイナー)とora2pg 25.0系。
まとめ:Oracle移行で先に決める4点
第一に、移行の動機を「Oracleのサポート期限」に置く説明は2026年8月時点では成り立ちません。19cのPremier Supportは2029年12月31日まで、Extended Supportは2032年12月31日まで延長済みだからです。判断の軸はライセンスと保守費の総額、構成の自由度、クラウド移行との同時実行へ移っています。
第二に、工数を左右するのはデータ量ではなくコード量です。ora2pgの評価レポートは難易度を「A・B・C」と「1から5」の組で返します。Aは自動変換だけで完了しうる移行、Bは書き換えを伴い人日が5日まで、Cは5日を超える移行を指す記号。数字は1が定型(ストアド関数もトリガも無い)、3が書き換え不要、5が書き換えを伴う段階を表します。
第三に、型の既定変換をそのまま通すと性能事故になります。ora2pgの既定マッピングはNUMBER(*,0)をnumeric(38)へ落とすためです。numericは十進の可変長型で演算がソフトウェア実装のため、結合キーや集計列がこの型で残ると移行後の応答が目に見えて鈍ります。桁数を確認してbigintへ寄せる作業を、設定ファイルで再現できる形にしてください。
第四に、空文字とNULLの扱いが異なります。Oracleは長さゼロの文字列をNULLとして扱いますが、PostgreSQLは両者を別の値として区別するからです。この差はエラーにならず条件式の結果だけが静かに変わるため、テスト設計に組み込まないと本番で発見することになります。
互換性差分は型・採番・階層問い合わせ・PL/SQLの四か所に集中する
データ型の既定マッピングとNUMBERをそのまま通したときの代償
ora2pgが持つ既定の型変換は、Oracle側の型名をPostgreSQLの近い型へ寄せる素直な内容です。主要なものを並べます。
| Oracleの型 | ora2pgの既定 | 実務での寄せ先 |
|---|---|---|
| VARCHAR2 | varchar | varchar または text |
| NUMBER(*,0) | numeric(38) | 桁に応じ integer や bigint |
| DATE | timestamp(0) | timestamp(0) のまま |
| CLOB | text | text |
| BLOB | bytea | bytea か外部ストレージ |
| RAW(16) | uuid | uuid(uuid-ossp が前提) |
| ROWID | oid | 代替キーを設計し直す |
注意すべきはNUMBERとDATEの二つ。NUMBER(*,0)は整数を意味しますが、既定ではnumeric(38)になります。任意精度の十進型はCPUの整数演算に載らないぶん、bigintより演算コストが大きく開くのです。主キーや集計対象の金額列がこの型で残ると、索引のサイズも結合の速度も悪化します。桁数の実測値をOracle側で取り、収まる列はbigintへ分けて設定に書いてください。
DATEのほうは逆に、PostgreSQLのdate型へ落としてはいけません。OracleのDATEは年月日に加えて時分秒を保持する型で、PostgreSQLのdateは日付だけを持つからです。既定のtimestamp(0)がこの差を吸収しており、名前が同じという理由で置き換えると時刻が丸ごと消えます。挙動が分かれる機能はマテリアライズドビューとは?通常ビューとの違いとOracle・PostgreSQLでの作成・リフレッシュのように個別に確認しておくと差分レビューが早くなります。
シーケンスの引き継ぎと空文字とNULLの差がアプリ挙動に出る経路
OracleのシーケンスはPostgreSQLにも同名の機能があるため、seq.NEXTVALをnextval関数の呼び出しへ書き換えれば形式上は通ります。ただし見落としやすいのが現在値の引き継ぎ。スキーマだけ先に作ってデータを後から流し込むと初期値のままなので、切替直後に主キー重複が起きます。移送の最後にsetvalで最大値プラス1へ合わせる工程を手順書の一行として持たせてください。
空文字とNULLの差は、書き換えではなく設計判断の問題です。ora2pgのNULL_EQUAL_EMPTYを有効にすると、IS NULL の判定を coalesce で空文字と突き合わせる形へ、IS NOT NULL の判定を NULL でないことと空文字でないことの論理積へ機械的に書き換えます。挙動は揃うものの、条件式が長くなって索引が効きにくくなる副作用あり。アプリを直せる立場なら、空文字をNULLへ正規化してこの指示は無効のまま進めるほうが素直でしょう。識別子の大文字小文字も同種の落とし穴で、引用符を付けずに小文字へ統一し、アプリ側のSQLも同じ規則へ揃えてください。
CONNECT BYをWITH RECURSIVEへ置き換えるときに落ちる列と順序
階層問い合わせはOracle固有の構文で、PostgreSQLには同じ書き方がありません。標準SQLの再帰共通表式へ書き換えます。
-- Oracle
SELECT emp_id, LEVEL AS lvl
FROM emp
START WITH mgr_id IS NULL
CONNECT BY PRIOR emp_id = mgr_id;
-- PostgreSQL
WITH RECURSIVE t AS (
SELECT emp_id, mgr_id, 1 AS lvl
FROM emp WHERE mgr_id IS NULL
UNION ALL
SELECT e.emp_id, e.mgr_id, t.lvl + 1
FROM emp e JOIN t ON e.mgr_id = t.emp_id
)
SELECT emp_id, lvl FROM t;
機械的に置換できるのはここまで。LEVELは再帰側でカウンタを持てば再現できますが、SYS_CONNECT_BY_PATHは経路を積み上げる列を自前で用意することになります。CONNECT_BY_ISLEAFは子の有無を判定する副問い合わせへ組み替えてください。
もう一つ、返る行の順序が変わります。Oracleの階層問い合わせは深さ優先で降りますが、再帰共通表式は既定で幅優先の並びになるからです。画面へそのまま出していた場合は表示順が階層の見た目と合わなくなるため、経路を保持する列を作って並べ替える対応が要ります。ORDER SIBLINGS BY を使っていた箇所も同じ扱いです。
パッケージと自律型トランザクションとヒントの受け皿を先に決める
設計判断が要るのは三つ。まずパッケージですが、PostgreSQLに同じ概念がありません。ora2pgの既定はパッケージをスキーマとして出力し、内部の関数をその配下へ並べる方式で、PACKAGE_AS_SCHEMAを無効にすると関数名を平たく展開する方式へ切り替わります。パッケージ変数のようにセッション内で状態を持つ書き方は移し替えられないので、その部分はアプリ側かテーブル側へ逃がす設計変更になります。書き換え先となるPL/pgSQL側の記法差と制約はPL/pgSQLとは?関数とプロシージャの違いと例外処理・カーソルで整理しました。
自律型トランザクションも直接の対応物がありません。ora2pgはdblinkかpg_background拡張を使ったラッパ関数へ翻訳する動きを持っています。監査ログを親トランザクションのロールバックと切り離す用途がほとんどなので、拡張を入れずに別コネクションを張るか非同期のキューへ寄せる設計変更も比較してください。
オプティマイザヒントは、Oracleのヒント句がPostgreSQLの標準機能に存在しないため、そのまま消えます。実行計画を意図した形へ寄せたい箇所は、統計情報の精度を上げる、部分索引や式索引を足す、プランナ関連のパラメータをセッション単位で設定する、といった手段へ置き換えます。Oracle互換の関数名を残したいなら orafce 拡張とUSE_ORAFCE指示の組み合わせが使えるでしょう。
ora2pgの実行手順は評価レポートを先に出してから設定へ落とす
ora2pgはOracleへ接続してスキーマを走査し、PostgreSQL向けのSQLスクリプトを生成するツールです。最新は25.0で、2025年4月20日の公開以降、2026年8月時点で後継のリリースはありません。評価・設定・出力の三段で進めます。
評価レポートで移行難易度と人日を数値にしてから着手可否を決める
最初に走らせるのは変換ではなく評価です。次のコマンドで、種別ごとの件数と書き換えが必要な箇所、人日換算の見積りを含むレポートが出ます。
ora2pg -c ora2pg.conf -t SHOW_REPORT --estimate_cost --dump_as_html
レポート末尾の Migration level が、まとめで触れたA・B・Cと1から5の組です。B-5であれば「書き換えを伴い5人日まで、ストアド関数やトリガに手作業の書き換えが要る」と読めます。人日の計算にはCOST_UNIT_VALUEという単位が使われ、既定は1単位あたり5分。この値はPostgreSQLに習熟した担当者を前提としており、公式の説明でも初めての移行なら10分へ設定するよう案内されています。
BとCの境界はHUMAN_DAYS_LIMITという指示で決まり、既定は10人日です。評価が10人日を超えるとCへ落ち、プロジェクト管理と移行支援を伴う規模だと機械的に判定されます。対象のインスタンスやスキーマが多数ある場合は、同梱の ora2pg_scanner で一括走査し、どのデータベースから着手するかを難易度順に並べる使い方も可能です。
変換の方針を設定ファイルへ固定して何度でも同じ結果を得る手順
決めた方針は、生成後のSQLを手で直すのではなく設定ファイルへ書きます。理由は再現性。設定に落としておけば、Oracle側にテーブルが追加されても同じコマンドで同じ変換結果が得られ、移行リハーサルを何度でも回せます。
DATA_TYPE NUMBER(*\,0):bigint
NULL_EQUAL_EMPTY 0
PACKAGE_AS_SCHEMA 1
USE_ORAFCE 0
AUTONOMOUS_TRANSACTION 1
DATA_TYPEは既定を全部書き直す必要はなく、変えたいものだけを列挙する形式です。精度と位取りを含む型を指定するときは、カンマをバックスラッシュで退避させる記法になります。列単位で例外を作りたい場合はMODIFY_TYPEという別の指示があるので、テーブルと列を名指しして個別に寄せる指定も可能です。
スキーマとデータを別の工程に分けて並列で流し込むときの段取り
出力は種別ごとに実行します。テーブル定義、ビュー、関数、トリガ、権限を別のファイルへ出し、流す順序を制御するのが安全でしょう。
ora2pg -c ora2pg.conf -t TABLE -o schema.sql
ora2pg -c ora2pg.conf -t FUNCTION -o func.sql
ora2pg -c ora2pg.conf -t COPY -j 4
データ移送はCOPY種別で行い、-jで並列度を指定します。25.0ではORACLE_FDW_COPY_FORMATという指示が加わり、oracle_fdw経由のデータ形式をBINARYかCSVから選べるようになりました。件数が多い表では、索引と外部キー制約を作る前に流し込み、後から制約を付ける順序に組み替えると所要時間が縮みます。
AWS SCTとDMSを使う構成と2026年時点で変わった三つの前提
移行先をAWS上のマネージドPostgreSQLに置く場合、スキーマ変換とデータ移送をAWSの機能で通す構成が選べます。ただし2026年に入って道具立てが変わっているため、古い手順書をそのまま踏襲すると存在しないサービスを前提にすることになります。
AWS SCTとDMS Schema Conversionは同じ変換エンジンの別入口
AWS Schema Conversion Tool(AWS SCT)は手元の端末で動かすJava製のツールで、公開されているビルドは677が最新です。このビルドで実行基盤がJava 11から17へ更新されました。一方のDMS Schema Conversionは、AWS DMSの機能としてコンソールから使うマネージド版。公式の説明どおりAWS SCTの変換エンジンの上に構築されており、違いは実行場所と運用方法です。
マネージド版は、インスタンスプロファイル、データプロバイダ、移行プロジェクトという三つの資源で構成されます。移行先がまだ無い段階では仮想ターゲットを指定して評価だけ先に進められるため、環境構築を待たずにアセスメントへ着手できるのが利点。規則ベースで変換しきれなかったオブジェクトには生成AIによる変換が用意されており、Oracleから Aurora PostgreSQL もしくは RDS for PostgreSQL への変換パスはその対象です。
生成AIによる変換が使えるリージョンと国内から選べる範囲の確認
移行プロジェクトを作れるリージョンと、生成AI変換が使えるリージョンは一致しません。アジアパシフィックでは東京(ap-northeast-1)と大阪(ap-northeast-3)、シドニー(ap-southeast-2)が対応する一方、ソウル・ムンバイ・シンガポールなどは移行プロジェクト自体は作れても生成AI変換を使えない配置。国内案件で東京か大阪を選ぶなら制約にはなりません。
2026年に使えなくなった棚卸しツールと最小インスタンスの扱い
まず、AWS DMS Fleet Advisorが2026年5月20日でサポートを終了しました。2025年5月20日以降は新規受付が止まっており、終了日以降はコンソールも資源も参照できません。AWSは代替としてAWS Migration Evaluatorへ移すよう案内しています。棚卸しをFleet Advisorで行う前提の手順書は成立しないわけです。
次に、DMSのレプリケーションインスタンスのうち t2.micro と t3.micro が2026年8月3日でサポート終了となり、以後は dms.t3.small へ自動的に引き上げられます。検証用に最小サイズを並べて費用を抑える組み立ては使えません。DMS自体の役割と料金はAWS Database Migration Service(DMS)とは?サーバーレスと同種・異種移行の使い分け・料金で整理しています。
フルロードと変更データの取り込みを分けて停止時間を縮める設計
データ移送は、全量を一度コピーするフルロードと、その後の更新を追いかける変更データ取り込みの二段で組みます。全量コピー中もOracle側は稼働させたままにでき、完了後は差分だけが流れるので、切替のために止める時間を分単位まで縮められるわけです。移行先の構成と料金の違いはAmazon RDS for PostgreSQLとは?マルチAZ構成・拡張機能の統制と延長サポート課金・DMS移行とAurora PostgreSQLとは?対応バージョン・拡張機能とBabelfish・RDSからの移行判断を突き合わせて判断してください。
アプリ改修とテスト計画で合格ラインをどこに置くかを決める進め方
書き換え対象のSQLを棚卸しして影響範囲を先に確定させる手順
移行が長引く原因の多くは改修対象の把握の遅れです。アプリ側に散らばるSQLは二方向から集めます。一つはOracle側の共有プールに残る実行済みSQLの一覧。ただし低頻度のバッチは取りこぼすので、ソースコードの文字列検索を併用します。探す対象は、ROWNUM、CONNECT BY、DECODE、NVL、SYSDATE、外部結合の旧記法、NEXTVAL、二重引用符付きの識別子の八つです。
ORMが生成するSQLは方言設定の切り替えで大半が追随するため、問題になるのは生SQLとページングの実装でしょう。ROWNUMで絞っていた処理はLIMITとOFFSETへ移りますが、並び順が確定していないと返る行が変わります。ORDER BYが無いページングは並び順を明示してください。
行数の一致だけでは足りない検証項目と性能の合格ラインの決め方
データ検証を件数の一致だけで済ませると、移行の失敗を見逃します。最低でも四つを揃えて比較してください。テーブルごとの行数、数値列の合計値、文字列列の空文字とNULLの件数、日付列の最小値と最大値です。三つ目は空文字の扱いの差を検出する項目で、Oracle側でNULL件数だけを数えていると差分が現れません。
性能の合格ラインは、平均値ではなく上位の遅い側で決めます。移行前のOracleで主要な画面と夜間バッチの応答時間を計測しておき、95パーセンタイルが一定の範囲へ収まることを条件にする形。基準を超える処理が出たら真っ先に疑うのは型で、numericのまま残った結合キーや集計列を整数型へ寄せるだけで戻ることが少なくありません。領域の肥大は運用フェーズの話で、PostgreSQLのVACUUM運用|autovacuumのしきい値設計とXID周回・肥大の切り分けに設定の考え方をまとめました。
移行するかどうかを決める三つの条件とライセンス費の回収年数の見方
ここまでの手順を踏まえて、移行を実行するか見送るかの判断を言い切ります。判断材料は三つで、いずれも着手前に数値化できるものです。
一つ目は、ora2pgの評価が返す移行レベル。A系またはB-3までなら、変換ツールの出力を確認しながら進める範囲で収まります。B-5は書き換えの本数が読める段階なので、要員と期間を確保すれば計画どおり進むでしょう。C-5が出た場合は、機能単位で切り出して段階的に移すか、アプリごと作り直す選択肢と比較すべき水準です。
二つ目は、商用データベース固有の機能への依存度です。可用性をクラスタ構成に頼っている、パーティションの自動管理を前提に運用設計している、性能分析が診断レポートに依存している、といった条件が三つ以上重なる環境は、移行後に運用手順を丸ごと作り直すことになります。この工数は変換ツールの見積りに入らないので、別建てで積んでください。
三つ目は回収年数。移行にかかる総費用を、Oracleのライセンス保守費と移行先の利用料の差額(年額)で割った値を出します。この年数が2年以内なら実行、3年を超えるなら見送りが妥当な線。2年から3年の間は、更改時期の近さや要員の確保見通しで決めることになります。移行先の費用側はPostgreSQLのライセンスと価格:無償の範囲と実際に払う費用・5年総額での判断にまとめました。
見送りが正解になる場面も明示しておきます。データセンターの老朽化が主因でクラウドへ移りたいだけなら、データベースの方言まで変える必要はありません。既存のライセンスを持ち込む構成が使えるなら、Oracle Database@AWSとは?AWSでOracle Exadata・Autonomous Databaseを利用できるマルチクラウドサービスのような選択肢のほうが停止時間もテスト量も小さく済みます。
判断が固まったあとの実務は、互換性差分の棚卸し・変換設定の作り込み・リハーサルの反復という地道な繰り返しになります。既存の業務システムを止めずに移行を通す設計と、移行後の保守まで含めて任せたい場合は、基幹システム開発で受託の範囲と進め方をご確認ください。
よくある質問
Babelfishを使えばOracleのアプリをそのまま動かせますか?
できません。BabelfishはSQL ServerのT-SQLと通信プロトコルに互換性を持たせる機能で、Oracle互換ではないからです。移行元がSQL Serverなら選択肢になりますが、Oracleからの移行では別の道具立て。Oracle固有の関数名を残したいなら orafce 拡張が近い役割を果たします。
ora2pgとAWS SCTはどちらを使うべきですか?
移行先で決めるのが分かりやすい基準です。移行先がAWS上のAurora PostgreSQLかRDS for PostgreSQLで、データ移送もDMSで通すなら、変換から移送まで同じ画面で完結するDMS Schema Conversionが素直でしょう。オンプレミスや他社クラウドが移行先なら、ora2pgのほうが設定で細かく制御できます。
移行先のPostgreSQLはどのメジャーバージョンを選ぶべきですか?
新規の移行なら18系を選びます。2026年8月時点で18が最新のメジャーで、最新マイナーは同月13日公開の18.6。サポート期限が2030年11月14日まであるため、移行直後に更改の話が再燃する事態を避けられます。14系を選ぶ判断は勧めません。2026年11月12日が最終リリースで、移行の完了とほぼ同時にサポートが切れるからです。
自律型トランザクションはどう置き換えるのが現実的ですか?
用途を確認するところから始めます。監査ログを残す用途であれば、dblinkやpg_background拡張でラッパ関数を作るほかに、ログ書き込みを別コネクションへ出す、メッセージキューへ非同期で流すといった設計変更が取れるはずです。拡張に頼ると移行先で使える拡張の一覧に縛られる点に注意してください。
移行のリハーサルは何回くらい回すものですか?
本番相当のデータ量で最低3回が目安です。1回目は手順の穴を見つけるため、2回目は所要時間を測るため、3回目は切替当日と同じ時間帯・同じ担当で通すため。所要時間が読めていないまま切替日を決めると、停止時間の超過という最も避けたい形で失敗します。