すべてのプロダクト
Search
ドキュメントセンター

AnalyticDB:自己管理型OracleアプリケーションからAnalyticDB for PostgreSQLインスタンスへのデータの移行

最終更新日:Sep 24, 2024

AnalyticDB for PostgreSQLは、Oracle構文と互換性があります。 このトピックでは、OracleアプリケーションからAnalyticDB for PostgreSQLインスタンスにデータを移行する方法について説明します。

Ora2Pgを使用した構文変換

Ora2Pgはオープンソースツールです。 このツールを使用して、Oracleのテーブル、ビュー、およびパッケージのDDLステートメントを、PostgreSQL構文と互換性のあるステートメントに変換できます。 詳細については、Ora2Pgのドキュメントを参照してください。

説明

スクリプト変換後のPostgreSQL構文バージョンはAnalyticDB for PostgreSQLインスタンスのマイナーエンジンバージョンよりも後であり、Ora2Pgがスクリプトを変換するルールが欠落しているか正しくない可能性があるため、変換されたSQLスクリプトを手動で修正する必要があります。

Oracleとの互換性

互换モードパラメータ

同じ関数の動作は異なり、データベースによって互換性がありません。 互換モードパラメーターを設定する必要があります。 PostgreSQL互換モードとOracle互換モードが利用可能です。

次の表に、互換モードを指定するためにAnalyticDB for PostgreSQLによって提供されるパラメーターを示します。

パラメーター

説明

adb_compatibility_mode

互換モード。 有効な値:

  • postgres (デフォルト): PostgreSQL互換モード。

  • oracle: Oracle互換モード。

このパラメーターを設定する前に、SHOW adb_compatibility_mode; ステートメントを実行して、パラメーターの現在の値を照会することを推奨します。

インスタンスレベルのパラメーターを変更する場合は、 チケットを起票して、サービスセンターにお問い合わせください。

文字列連結演算子の互換モード

文字列連結式 'abc' | | NULLでは、'abc'NULLは定数、または実表や計算結果のデータです。

  • PostgreSQL互換モードでは、式の戻り値はNULLです。 PostgreSQLでは、NULLを使用した文字列の連結によってNULLが生成されます。

  • Oracle互換モードでは、式の戻り値は 'abc' です。 Oracleでは、NULLは単一引用符 (') で囲まれた空の文字列と同じです。

    重要

    Oracle互換モードで文字列連結機能を使用する前に、Laser. enable = offを使用してレーザーエンジンを無効にする必要があります。

データ型のサポート

AnalyticDB for PostgreSQLは、互換性モードパラメーターを設定することなく、定数文字列のデータ型をサポートします。

CREATE TABLE as SELECTなどのステートメントを実行すると、定数文字列がUNKNOWN型ではなくTEXT型として自動的に認識されます。

Orafce拡張機能を使用する

AnalyticDB for PostgreSQLは、Orafce拡張機能を提供します。 この拡張機能は、Oracleと互換性のある機能をサポートします。 これらの関数は、AnalyticDB for PostgreSQLで変更または変換することなく使用できます。

Orafceを使用する前に、次のステートメントを実行してOrafceをインストールします。

CREATE EXTENSION orafce;

次の表に、Orafceが提供するOracle互換関数を示します。

表 1 Orafceが提供するOracle互換関数

関数

説明

nvl(anyelement, anyelement)

  • 最初の引数の値がnullの場合、この関数は2番目の引数の値を返します。

  • 最初の引数の値がnullでない場合、この関数は最初の引数の値を返します。

説明

2つの引数のデータ型は同じでなければなりません。

  • SELECT nvl(null,1);

    次の情報が返されます。

    nvl
    -----
      1
    (1 row)
  • SELECT nvl(0,1);

    次の情報が返されます。

    nvl
    -----
      0
    (1 row)
  • SELECT nvl(0,null);

    次の情報が返されます。

    nvl
    -----
      0
    (1 row)

add_months(day date, value int)RETURNS date

この関数は、最初の引数で指定された日付に、2番目の引数で指定された月数を追加して日付を返します。

SELECT add_months(current_date, 2);

次の情報が返されます。

add_months
------------
2019-08-31
(1 row)

last_day (値の日付)

この関数は、指定された日付の月の最終日を返します。 戻り値は日付です。

SELECT last_day('2018-06-01');

次の情報が返されます。

 last_day
------------
2018-06-30
(1 row)

next_day (値の日付、平日のテキスト)

  • 最初の引数は開始日を指定します。

  • 2番目の引数は、曜日を指定します。 例: 金曜日。

この関数は、開始日から2週目の日を表す日付を返します。 例: 第2金曜日を表す日付。

SELECT next_day(current_date, 'FRIDAY');

次の情報が返されます。

 next_day
------------
2019-07-05
(1 row)

next_day(value date, weekday integer)

  • 最初の引数は開始日を指定します。

  • 2番目の引数は、曜日を表す数値を指定します。 数は1から7の範囲です。 値1は日曜日を表し、値2は月曜日を表す。 同様に、値7は土曜日を表す。

この関数は、開始日より特定の日数後の日付を返します。

  • SELECT next_day('2019-06-22', 1);

    次の情報が返されます。

     next_day
    ------------
    2019-06-23
    (1 row)
  • SELECT next_day('2019-06-22', 2);

    次の情報が返されます。

     next_day
    ------------
    2019-06-24
    (1 row)

months_between(date1 date, date2 date)

この関数は、date1とdate2の間の月数を返します。

  • date1がdate2より後の場合、戻り値は正です。

  • date1がdate2より前の場合、戻り値は負です。

  • SELECT months_between('2019-01-01', '2018-11-01');

    次の情報が返されます。

    months_between
    ----------------
                 2
    (1 row)
  • SELECT months_between('2018-11-01', '2019-01-01');

    次の情報が返されます。

    months_between
    ----------------
                -2
    (1 row)

trunc (タイムゾーン付きの値タイムスタンプ、fmtテキスト)

  • 最初の引数は、切り捨てたいタイムスタンプを指定します。

  • 2番目の引数は、年、月、日、週、時間、分、秒など、タイムスタンプの切り捨てに基づく精度を指定します。

    • Y: タイムスタンプが、タイムスタンプに対応する年の最初の日に切り捨てられることを指定します。

    • Q: タイムスタンプが、タイムスタンプに対応する四半期の最初の日に切り捨てられることを指定します。

  • SELECT TRUNC(current_date,'Q');

    次の情報が返されます。

      trunc
    ------------
    2019-04-01
    (1 row)
  • SELECT TRUNC(current_date,'Y');

    次の情報が返されます。

      trunc
    ------------
    2019-01-01
    (1 row)

trunc (タイムゾーン付きの値タイムスタンプ)

この関数はタイムスタンプを切り捨てます。 指定されたタイムスタンプの時、分、秒の値はデフォルトで切り捨てられます。

SELECT TRUNC('2019-12-11'::timestamp);

次の情報が返されます。

        trunc
------------------------
2019-12-11 00:00:00+08
(1 row)

trunc (値の日付)

この関数は日付を切り捨てます。

SELECT TRUNC('2019-12-11'::timestamp,'Y');

次の情報が返されます。

        trunc
------------------------
2019-01-01 00:00:00+08

ラウンド (タイムスタンプとタイムゾーン、fmtテキスト)

この関数は、週や日などの単位に基づいて最も近い値にタイムスタンプを丸めます。

SELECT round('2018-10-06 13:11:11'::timestamp, 'YEAR');

次の情報が返されます。

        round
------------------------
2019-01-01 00:00:00+08
(1 row)

round(value timestamp with time zone)

この関数は、単位日に基づいて最も近い値にタイムスタンプを丸めます。

SELECT round('2018-10-06 13:11:11'::timestamp);

次の情報が返されます。

        round
------------------------
2018-10-07 00:00:00+08
(1 row)

ラウンド (値の日付、fmtテキスト)

この関数は丸められた日付を返します。

  • SELECT round(TO_DATE('27-OCT-00','DD-MON-YY'), 'YEAR');

    次の情報が返されます。

      round
    ------------
    2001-01-01
    (1 row)
  • SELECT round(TO_DATE('27-FEB-00','DD-MON-YY'), 'YEAR');

    次の情報が返されます。

      round
    ------------
    2000-01-01
    (1 row)

ラウンド (値の日付)

この関数は丸められた日付を返します。

SELECT round(TO_DATE('27-FEB-00','DD-MON-YY'));

次の情報が返されます。

  round
------------
2000-02-27
(1 row)

instr(str text, patt text, start int, nth int)

この関数は、文字列の部分文字列を検索します。 部分文字列が取得された場合、関数は部分文字列の位置を返します。 それ以外の場合、関数は0を返します。

  • start: 検索の開始位置を指定します。

  • nth: 部分文字列のn番目のオカレンスの位置を指定します。

  • SELECT instr('Greenplum', 'e',1,2);

    次の情報が返されます。

    instr
    -------
        4
    (1 row)
  • SELECT instr('Greenplum', 'e',1,1);

    次の情報が返されます。

    instr
    -------
        3
    (1 row)

instr(str text, patt text, start int)

n番目の引数は指定されていません。 この関数は、部分文字列の最初の出現の位置を返します。

SELECT instr('Greenplum', 'e',1);

次の情報が返されます。

instr
-------
    3
(1 row)

instr(str text, patt text)

start引数が指定されていません。 この関数は、文字列の先頭から部分文字列を検索します。

SELECT instr('Greenplum', 'e');

次の情報が返されます。

instr
-------
    3
(1 row)

plvstr.rvrs(str text, start int, end int)

この関数は、指定した文字列の文字の順序を逆にします。 str引数は文字列を指定し、start引数とend引数は順序を逆にする文字の開始位置と終了位置を指定します。

SELECT plvstr.rvrs('adb4pg', 5,6);

次の情報が返されます。

reverse
---------
gp
(1 row)

plvstr.rvrs(str text, start int)

この関数は、start引数で指定された文字から文字列の末尾まで文字の順序を逆にします。

SELECT plvstr.rvrs('adb4pg', 4);

次の情報が返されます。

reverse
---------
gp4
(1 row)

plvstr.rvrs(strテキスト)

この関数は、文字列全体の順序を逆にします。

SELECT plvstr.rvrs('adb4pg');

次の情報が返されます。

reverse
---------
gp4bda
(1 row)

concat (テキスト、テキスト)

この関数は2つの文字列を結合します。

SELECT concat('adb','4pg');

次の情報が返されます。

concat
--------
adb4pg
(1 row)

concat(text, anyarray)/concat(anyarray, text)/concat(anyarray, anyarray)

この関数は、同じまたは異なるデータ型のデータを結合します。

  • SELECT concat('adb4pg', 6666);

    次の情報が返されます。

      concat
    ------------
    adb4pg6666
    (1 row)
  • SELECT concat(6666, 6666);

    次の情報が返されます。

     concat
    ----------
    66666666
    (1 row)
  • SELECT concat(current_date, 6666);

    次の情報が返されます。

        concat
    ----------------
    2019-06-306666
    (1 row)

nanvl(float4, float4)/nanvl(float4, float4)/nanvl(numeric, numeric)

最初の引数がNUMERICデータ型の場合、この関数は最初の引数の値を返します。 それ以外の場合、この関数は2番目の引数の値を返します。

  • SELECT nanvl('NaN', 1.1);

    次の情報が返されます。

    nanvl
    -------
      1.1
    (1 row)
  • SELECT nanvl('1.2', 1.1);

    次の情報が返されます。

    nanvl
    -------
      1.2
    (1 row)

bitand(bigint, bigint)

この関数は、INTEGERデータ型の2つの2進数に対してAND演算を実行します。 1行のみが返されます。

  • SELECT bitand(1,3);

    次の情報が返されます。

    bitand
    --------
         1
    (1 row)
  • SELECT bitand(2,6);

    次の情報が返されます。

    bitand
    --------
         2
    (1 row)
  • SELECT bitand(4,6);

    次の情報が返されます。

    bitand
    --------
         4
    (1 row)

listagg (テキスト)

この関数は、テキストのクラスタ化文字列を返します。

SELECT listagg(t) FROM (VALUES('abc'), ('def')) as l(t);

次の情報が返されます。

listagg
---------
abcdef
(1 row)

listagg (テキスト、テキスト)

この関数は、テキストのクラスタ化文字列を返します。 2番目の引数の値が区切り文字として使用されます。

SELECT listagg(t, '.') FROM (VALUES('abc'), ('def')) as l(t);

次の情報が返されます。

listagg
---------
abc.def
(1 row)

nvl2(anyelement, anyelement, anyelement)

最初の引数の値がnullの場合、この関数は3番目の引数の値を返します。 それ以外の場合、この関数は2番目の引数の値を返します。

  • SELECT nvl2(null, 1, 2);

    次の情報が返されます。

    nvl2
    ------
       2
    (1 row)
  • SELECT nvl2(0, 1, 2);

    次の情報が返されます。

    nvl2
    ------
       1
    (1 row)

lnnvl(bool)

引数の値がnullまたはfalseの場合、この関数はtrueを返します。 引数の値がtrueの場合、この関数はfalseを返します。

  • SELECT lnnvl(null);

    次の情報が返されます。

    lnnvl
    -------
    t
    (1 row)
  • SELECT lnnvl(false);

    次の情報が返されます。

    lnnvl
    -------
    t
    (1 row)
  • SELECT lnnvl(true);

    次の情報が返されます。

    lnnvl
    -------
    f
    (1 row)

ダンプ ("any")

この関数は、データ型コード、バイト単位の長さ、および引数の内部表現を含むテキストを返します。

SELECT  dump('adb4pg');

次の情報が返されます。

                dump
---------------------------------------
Typ=705 Len=7: 97,100,98,52,112,103,0
(1 row)

ダンプ ("any", integer)

2番目の引数は、戻り値の形式を指定します。 形式は、10進数表記 (10で指定) または16進数表記 (16で指定) にすることができます。

  • SELECT dump('adb4pg', 10);

    次の情報が返されます。

                    dump
    ---------------------------------------
    Typ=705 Len=7: 97,100,98,52,112,103,0
    (1 row)
  • SELECT dump('adb4pg', 16);

    次の情報が返されます。

                   dump
    ------------------------------------
    Typ=705 Len=7: 61,64,62,34,70,67,0
    (1 row)
  • SELECT dump('adb4pg', 2);

    次の情報が返されます。

    ERROR:  unknown format (others.c:430)

nlssort (テキスト、テキスト)

この関数は、特定の順序でデータをソートします。

次のステートメントを実行して、テーブルを作成し、データを挿入します。

CREATE TABLE t1 (name text);
INSERT INTO t1 VALUES('Anne'), ('anne'), ('Bob'), ('bob');
  • SELECT * FROM t1 ORDER BY nlssort(name, 'en_US.UTF-8');

    次の情報が返されます。

    name
    ------
    anne
    Anne
    bob
    Bob
    (4 row)
  • SELECT * FROM t1 ORDER BY nlssort(name, 'C');

    次の情報が返されます。

    name
    ------
    Anne
    Bob
    anne
    bob
    (4 row)

substr(str text, start int)

この関数は、最初の引数で指定された文字列から部分文字列を取得します。 2番目の引数は、部分文字列の開始位置を指定します。

  • SELECT substr('adb4pg', 1);

    次の情報が返されます。

    substr
    --------
    adb4pg
    (1 row)
  • SELECT substr('adb4pg', 4);

    次の情報が返されます。

    substr
    --------
    4pg
    (1 row)

substr(str text, start int, len int)

3番目の引数は、部分文字列の終了位置を指定します。 この引数の値は、開始引数の値以上で、文字列の長さ以下である必要があります。

SELECT substr('adb4pg', 5,6);

次の情報が返されます。

substr
--------
pg
(1 row)

pg_catalog.substring (varchar2, integer, integer)

この関数は、VARCHAR2データ型の文字列から部分文字列を返します。 2番目の引数は部分文字列の開始位置を指定し、3番目の引数は部分文字列の終了位置を指定します。

SELECT  substr('adb4pg'::varchar2, 5,6);

次の情報が返されます。


substr
--------
pg
(1 row)

pg_catalog.substring (varchar2, integer)

この関数は、VARCHAR2データ型の文字列から部分文字列を返します。 部分文字列は、2番目の引数で指定された文字から始まり、文字列の最後まで続きます。

SELECT substr('adb4pg'::varchar2, 4) ;

次の情報が返されます。

substr
--------
4pg
(1 row)

pg_catalog.lengthb(varchar2)

この関数は、VARCHAR2データ型の文字列のバイト数を返します。 nullを指定した場合、関数はnullを返します。 空の文字列が指定されている場合、関数は0を返します。

  • SELECT lengthb('adb4pg'::varchar2) ;

    次の情報が返されます。

    lengthb
    ---------
          6
    (1 row)
  • SELECT lengthb('analytics'::varchar2);

    次の情報が返されます。

    lengthb
    ---------
          9
    (1 row)

lpad(string char、length int、fill char)

この関数は、文字列のシーケンスで指定された長さに左側の文字列をパディングします。

  • 最初の引数は、左側にパディングする文字列を指定します。

  • 2番目の引数は、パディング後の結果文字列の長さを指定します。

  • 3番目の引数は、パディングに使用される文字列を指定します。

説明

CHAR型の文字列の場合、PostgreSQLは末尾のスペースを削除しますが、Oracleは削除しません。

SELECT lpad('abc '::char(4),6,'x');

次の情報が返されます。

  lpad
--------
 xxabc
(1 row)

lpad (文字列char、長さint)

この関数は、左側の文字列を指定した長さにスペースでパディングします。

SELECT lpad('abc '::char(4),6);

次の情報が返されます。

  lpad
--------
   abc
(1 row)

regexp_count (文字列テキスト、パターンテキスト、startPos int、フラグテキスト)

この関数は、開始位置からソース文字列でパターンが発生する回数を返します。 戻り値は整数でなければなりません。 パターンが見つからない場合、関数は0を返します。

  • 最初の引数は、ソース文字列を指定します。

  • 2番目の引数はパターンを指定します。

  • 3番目の引数は、検索の開始位置を指定します。 正の整数でなければなりません。 ソース文字列の末尾からパターンを検索することはできません。

  • 4番目の引数には、関数のデフォルトの一致動作を変更するために使用できる文字式を指定します。 次の文字を1つ以上含めることができます。

    • 'i': 大文字と小文字を区別しないマッチング。 デフォルトでは、大文字と小文字を区別する照合とアクセントを区別する照合が使用されます。

    • 'c': 大文字と小文字を区別するマッチング。

    • 'n': ピリオド (.) を改行と一致させます。 デフォルトでは、ピリオド (.) は改行と一致しません。

    • 'm': ソース文字列を複数行として扱います。 デフォルトでは、ソース文字列は1行として扱われます。

    • 'x': 空白文字を無視します。 デフォルトでは、空白文字は一致します。

  • SELECT regexp_count('a'||CHR(10)||'d', 'a.d', 1, 'n');

    次の情報が返されます。

     regexp_count 
    --------------
                1
    (1 row)
  • SELECT regexp_count('a'||CHR(10)||'d', 'a.d', 1, 'n');

    次の情報が返されます。

     regexp_count 
    --------------
                1
    (1 row)

regexp_count (文字列テキスト、パターンテキスト、startPos int)

この関数は、文字列の開始位置からソース文字列内でパターンが発生する回数を返します。 戻り値は整数でなければなりません。 パターンが見つからない場合、関数は0を返します。

SELECT regexp_count('abc', '[a-z]',3);

次の情報が返されます。

 regexp_count
--------------
            1
(1 row)

regexp_count (文字列テキスト、パターンテキスト)

この関数は、文字列の先頭からソース文字列でパターンが発生する回数を返します。 戻り値は整数でなければなりません。 パターンが見つからない場合、関数は0を返します。

SELECT regexp_count('abc', '[a-z]');

次の情報が返されます。

 regexp_count
--------------
            3
(1 row)

regexp_instr (文字列テキスト、パターンテキスト、startPos int、occurrence int、return_opt int、フラグテキスト、グループint)

この関数は、ソース文字列内のパターンの開始位置または終了位置を返します。 戻り値は整数でなければなりません。

  • 最初の引数は、ソース文字列を指定します。

  • 2番目の引数はパターンを指定します。

  • 3番目の引数は、検索の開始位置を指定します。 正の整数でなければなりません。 ソース文字列の末尾からパターンを検索することはできません。

  • 4番目の引数は、検索を開始するソース文字列でのパターンの発生を指定します。 正の整数でなければなりません。 デフォルト値は1です。これは、パターンの最初の出現から検索が開始されることを示します。

  • 5番目の引数は、ソース文字列内のパターンの開始位置または終了位置を指定します。 有効な値:

    • 0 (デフォルト): オカレンスの最初の文字の位置。

    • 1: オカレンスに続くキャラクターの位置。

  • 6番目の引数は、関数のデフォルトの一致動作を変更するために使用できる文字式を指定します。 詳細については、「REGEXP_COUNT」をご参照ください。

  • 7番目の引数は、パターン内のキャプチャグループのシリアル番号を指定します。 正の整数でなければなりません。 捕捉グループは入れ子にすることができる。 捕捉グループは、それらの左括弧がパターンに現れる順序に基づいて番号付けされる。 値が0の場合、パターンに一致する部分文字列全体の位置が返されます。 値がパターン内のキャプチャグループの数より大きい場合、関数は0を返します。 デフォルト値:0

SELECT regexp_instr('abxxabc','(a)(b)(c)',1,1,0,'',2);

次の情報が返されます。

 regexp_instr
--------------
            6
(1 row)

regexp_instr (文字列テキスト、パターンテキスト、startPos int、occurrence int、return_opt int、フラグテキスト)

この関数は、文字列の開始位置からソース文字列内のパターンの指定されたオカレンスの開始位置または終了位置を返します。 戻り値は整数でなければなりません。

  • return_optは、ソース文字列内のパターンの開始位置または終了位置を指定します。 有効な値:

    • 0 (デフォルト): オカレンスの最初の文字の位置。

    • 1: オカレンスに続くキャラクターの位置。

  • flagsは、関数のデフォルトの一致動作を変更するために使用できる文字式を指定します。 詳細については、「REGEXP_COUNT」をご参照ください。

SELECT regexp_instr('abxxabc','(a)(b)(c)',1,1,0,'');

次の情報が返されます。

 regexp_instr
--------------
            5
(1 row)

regexp_instr (文字列テキスト、パターンテキスト、startPos int、occurrence int、return_opt int)

この関数は、文字列の開始位置からソース文字列内のパターンの指定されたオカレンスの開始位置または終了位置を返します。 戻り値は整数でなければなりません。

return_optは、ソース文字列内のパターンの開始位置または終了位置を指定します。 有効な値:

  • 0 (デフォルト): オカレンスの最初の文字の位置。

  • 1: オカレンスに続くキャラクターの位置。

SELECT regexp_instr('abc','[a-z]{3}',1,1,1);

次の情報が返されます。

 regexp_instr
--------------
            4
(1 row)

regexp_instr (文字列テキスト、パターンテキスト、startPos int、occurrence int)

この関数は、文字列の開始位置からソース文字列内のパターンの指定されたオカレンスの位置を返します。 戻り値は整数でなければなりません。

SELECT regexp_instr('abcd','[a-z]{2}',1,2);

次の情報が返されます。

 regexp_instr
--------------
            3
(1 row)

regexp_instr (文字列テキスト、パターンテキスト、startPos int)

この関数は、文字列の開始位置からソース文字列内のパターンの位置を返します。 戻り値は整数でなければなりません。

SELECT regexp_instr('abc','[a-z]',2);

次の情報が返されます。

 regexp_instr
--------------
            2
(1 row)

regexp_instr (文字列テキスト、パターンテキスト)

この関数は、文字列の先頭からのソース文字列内のパターンの位置を返します。 戻り値は整数でなければなりません。

SELECT regexp_instr('abc','[a-z]');

次の情報が返されます。

 regexp_instr
--------------
            1
(1 row)

regexp_like (文字列テキスト、パターンテキスト、フラグテキスト)

ソース文字列の部分文字列がパターンと一致する場合、この関数はtrueを返します。 それ以外の場合、この関数はfalseを返します。

  • 最初の引数は、ソース文字列を指定します。

  • 2番目の引数はパターンを指定します。

  • 3番目の引数には、関数のデフォルトの一致動作を変更するために使用できる文字式を指定します。 詳細については、「REGEXP_COUNT」をご参照ください。

SELECT regexp_like('a'||CHR(10)||'d', 'a.d', 'n');

次の情報が返されます。

 regexp_like
-------------
 t
(1 row)

regexp_like (文字列テキスト、パターンテキスト)

ソース文字列の部分文字列がパターンと一致する場合、この関数はtrueを返します。 それ以外の場合、この関数はfalseを返します。

SELECT regexp_like('abc', '[a-z]');

次の情報が返されます。

 regexp_like
-------------
 t
(1 row)

regexp_subth (文字列テキスト、パターンテキスト、startPos int、occurrence int、フラグテキスト)

この関数は、パターンに一致するソース文字列の部分文字列を返します。

  • 最初の引数は、ソース文字列を指定します。

  • 2番目の引数はパターンを指定します。

  • 3番目の引数は、検索の開始位置を指定します。 正の整数でなければなりません。 ソース文字列の末尾からパターンを検索することはできません。

  • 4番目の引数は、検索を開始するソース文字列でのパターンの発生を指定します。 正の整数でなければなりません。 デフォルト値は1です。これは、パターンの最初の出現から検索が開始されることを示します。

  • 5番目の引数には、関数のデフォルトの一致動作を変更するために使用できる文字式を指定します。 詳細については、「REGEXP_COUNT」をご参照ください。

SELECT regexp_substr('a,bc,def', '[^,]+',1,2,'');

次の情報が返されます。

 regexp_substr
---------------
 bc
(1 row)

regexp_subth (文字列テキスト、パターンテキスト、startPos int、occurrence int)

この関数は、文字列の開始位置から指定されたオカレンスのパターンと一致するソース文字列の部分文字列を返します。

SELECT regexp_substr('a,bc,def', '[^,]+',4,2);

次の情報が返されます。

 regexp_substr
---------------
 def
(1 row)

regexp_substr (文字列テキスト、パターンテキスト、startPos int)

この関数は、文字列の開始位置からパターンに一致するソース文字列の部分文字列を返します。

SELECT regexp_substr('a,bc,def', '[^,]+',4);

次の情報が返されます。

 regexp_substr
---------------
 c
(1 row)

regexp_subth (文字列テキスト、パターンテキスト)

この関数は、文字列の先頭からのパターンと一致するソース文字列の部分文字列を返します。

SELECT regexp_substr('a,bc,def', '[^,]+');

次の情報が返されます。

 regexp_substr
---------------
 a
(1 row)

上記の機能に加えて、OrafceはOracleのVARCHAR2データ型と互換性があります。

次の表に、OrafceをインストールせずにAnalyticDB for PostgreSQLでサポートできるOracle関数を示します。

関数

説明

sinh (フロート)

この関数は、双曲正弦値を返します。

SELECT sinh(0.1);

次の情報が返されます。

      sinh
-------------------
0.100166750019844
(1 row)

tanh (フロート)

この関数は、双曲正接値を返します。

SELECT  tanh(3);

次の情報が返されます。

      tanh
------------------
0.99505475368673
(1 row)

cosh (フロート)

この関数は、双曲線余弦値を返します。

SELECT cosh(0.2);

次の情報が返されます。

      cosh
------------------
1.02006675561908
(1 row)

decode (式、値、return [、value、return]... [, デフォルト])

この関数は、式の値を検索します。 値が見つかった場合、関数は値を返します。 それ以外の場合、関数はデフォルト値を返します。

次のステートメントを実行して、テーブルを作成し、データを挿入します。

CREATE TABLE t1(id int, name varchar(20));
INSERT INTO t1 values(1,'alibaba');
INSERT INTO t1 values(2,'adb4pg');
  • SELECT decode(id, 1, 'alibaba', 2, 'adb4pg', 'not found') from t1;

    次の情報が返されます。

     case
    ---------
    alibaba
    adb4pg
    (2 rows)
  • SELECT decode(id, 3, 'alibaba', 4, 'adb4pg', 'not found') from t1;

    次の情報が返されます。

      case
    -----------
    not found
    not found
    (2 rows)

Oracleデータ型とAnalyticDB for PostgreSQLデータ型のマッピング

オラクル

AnalyticDB for PostgreSQL

VARCHAR2

varcharまたはテキスト

日付

timestamp

LONG

text

LONG RAW

bytea

CLOB

text

NCLOB

text

BLOB

bytea

RAW

bytea

ROWID

oid

FLOAT

ダブル精度

DEC

decimal

DECIMAL

decimal

DOUBLE PRECISION

ダブル精度

INT

int

INTEGER

integer

REAL

real

SMALLINT

smallint

NUMBER

numeric

BINARY_FLOAT

ダブル精度

BINARY_DOUBLE

ダブル精度

TIMESTAMP

timestamp

XMLTYPE

xml

BINARY_INTEGER

integer

PLS_INTEGER

integer

TIMESTAMP WITH TIME ZONE

タイムゾーンのタイムスタンプ

ローカルタイムゾーン付きタイムスタンプ

タイムゾーンのタイムスタンプ

Oracle関数とAnalyticDB for PostgreSQL関数間のマッピング

オラクル

AnalyticDB for PostgreSQL

sysdate

現在のタイムスタンプ

trunc

truncまたは日付trunc

dbms_output.put_line

RAISEステートメント

デコード

またはデコード

NVL

合体

PL/SQLでのデータの変換

手続き型言語 /SQL (PL/SQL) は、Oracleによって提供されるSQLの手続き型言語拡張です。 PL/SQLは、SQLの一般的なプログラミング言語の機能をサポートしており、複雑なビジネスロジックを実装するために使用できます。 PL/SQLは、AnalyticDB for PostgreSQLのPL/pgSQLをマップします。

パッケージ

PL/pgSQLはパッケージをサポートしていません。 パッケージをスキーマに変換する必要があります。 パッケージ内のすべてのプロシージャと関数は、AnalyticDB for PostgreSQLでサポートされている関数に変換する必要があります。

例:

CREATE OR REPLACE PACKAGE pkg IS 

...

END;

変換結果:

CREATE SCHEMA pkg;
  • パッケージで定義されている変数

    プロシージャと関数のローカル変数は変更されず、グローバル変数はAnalyticDB for PostgreSQLの一時テーブルに格納できます。

  • パッケージ初期化ブロック

    パッケージ初期化ブロックを削除する必要があります。 ブロックを削除できない場合は、それらを関数にカプセル化し、必要に応じて関数を呼び出します。

  • パッケージで定義されているプロシージャと関数

    パッケージで定義されているプロシージャと関数を、AnalyticDB for PostgreSQLでサポートされている関数に変換します。 各関数は、使用されているパッケージに対応するスキーマで定義する必要があります。

    たとえば、pkgという名前のパッケージには次の関数が含まれます。

    FUNCTION test_func (args int) RETURN int is
    var number := 10;
    BEGIN
    ...
    END;

    上記の関数は、AnalyticDB for PostgreSQLでサポートされている次の関数に変換する必要があります。

    CREATE OR REPLACE FUNCTION pkg. test_func(args int) RETURNS int AS
    $$
    
      ...
    
    $$
     LANGUAGE plpgsql;

プロシージャ /関数

Oracleのパッケージ固有およびグローバルプロシージャと関数を、AnalyticDB for PostgreSQLでサポートされている関数に変換します。

例:

CREATE OR REPLACE FUNCTION test_func (v_name varchar2, v_version varchar2)
RETURN varchar2 IS
    ret varchar(32);
BEGIN
    IF v_version IS NULL THEN
        ret := v_name;
ELSE
    ret := v_name || '/' || v_version;
    END IF;
    RETURN ret;
END;

変換結果:

CREATE OR REPLACE FUNCTION test_func (v_name varchar, v_version varchar)
RETURNS varchar AS
$$

DECLARE
    ret varchar(32);
BEGIN
    IF v_version IS NULL THEN
        ret := v_name;
ELSE
    ret := v_name || '/' || v_version;
    END IF;
    RETURN ret;
END;

$$
 LANGUAGE plpgsql;

プロシージャまたは関数を変換する前に、次の情報に注意してください。

  • RETURNキーワードをRETURNSに変換します。

  • お使い&dollar ;\$... &dollar ;\$ 関数本体をカプセル化します。

  • 関数言語の宣言に注意してください。

  • サブプロシージャをAnalyticDB for PostgreSQLでサポートされている関数に変換します。

PLステートメント

  • ステートメントのため

    PL/SQLとPL/pgSQLでは、REVERSEを使用した整数FOR LOOPステートメントの動作が異なります。

    • PL/SQLは、2番目の数から1番目の数にカウントダウンします。

    • PL/pgSQLは、最初の数から2番目の数までカウントダウンします。

    したがって、変換中にループ境界を交換する必要があります。 例:

    逆のiのための

    FOR i IN REVERSE 1..3 LOOP
        DBMS_OUTPUT.PUT_LINE (TO_CHAR(i));
    END LOOP;

    変換結果:

    逆のiのための

    FOR i IN REVERSE 3..1 LOOP
        RAISE '%' ,i;
    END LOOP;
  • PRAGMAステートメント

    AnalyticDB for PostgreSQLはPRAGMAステートメントをサポートしていません。 PRAGMAステートメントを削除する必要があります。

  • トランザクション処理

    AnalyticDB for PostgreSQLの関数は、BEGIN、COMMIT、ROLLBACKなどのトランザクション制御ステートメントをサポートしていません。

    これらのステートメントは、次のルールに基づいて処理する必要があります。

    • 関数本体のトランザクション制御ステートメントを削除し、関数本体の外部に含めます。

    • COMMITおよびROLLBACKステートメントに基づいて関数を分割します。

  • EXECUTE 文

    AnalyticDB for PostgreSQLは、Oracleで提供されているものと同様の動的SQLステートメントをサポートします。 次の違いに注意してください。

    • AnalyticDB for PostgreSQLの動的SQL文は、USING構文をサポートしていません。 パラメーターをSQL文字列に結合する必要があります。

    • データベース識別子はquote_identを使用してパッケージ化され、数値はquote_literalを使用してパッケージ化されます。

    例:

    EXECUTE 'UPDATE employees_temp SET commission_pct = :x' USING a_null;

    変換結果:

    EXECUTE 'UPDATE employees_temp SET commission_pct = ' || quote_literal(a_null);
  • パイプROW関数

    AnalyticDB for PostgreSQLのテーブル関数を使用して、PIPE ROW関数を置き換えます。

    例:

    TYPE pair IS RECORD(a int, b int);
    TYPE numset_t IS TABLE OF pair;
    
    FUNCTION f1(x int) RETURN numset_t PIPELINED IS
    DECLARE
        v_p pair;
    BEGIN
        FOR i IN 1..x LOOP
          v_p.a := i;
          v_p.b := i+10;
          PIPE ROW(v_p);
        END LOOP;
        RETURN;
    END;
    
    select * from f1(10);

    変換結果:

    CREATE TYPE pair AS (a int, b int);
    
    CREATE OR REPLACE FUNCTION f1(x int) RETURNS SETOF PAIR AS
    $$
    
    DECLARE
    REC PAIR;
    BEGIN
        FOR i IN 1..x loop
            REC := row(i, i+10);
            RETURN NEXT REC;
        END LOOP;
        RETURN ;
    END
    
    $$
     language 'plpgsql';
    
    SELECT * FROM f1(10);
  • 例外処理

    • RAISEステートメントを使用して、例外をスローします。

    • 例外がキャッチされた後、対応するトランザクションはロールバックできません。 ロールバックは、ユーザー定義関数の外部でのみ許可されます。

    • AnalyticDB For PostgreSQLでサポートされているエラーコードの詳細については、PostgreSQL公式Webサイトをご覧ください。

  • return引数とout引数を含む関数

    AnalyticDB for PostgreSQLでは、関数にreturn引数とout引数を同時に含めることはできません。 return引数をout引数に変換する必要があります。

    例:

    CREATE OR REPLACE FUNCTION test_func(id int, name varchar(10), out_id out int) returns varchar(10)
    AS $body$
    BEGIN
          out_id := id + 1;
          return name;
    end
    $body$
    LANGUAGE PLPGSQL;

    変換結果:

    CREATE OR REPLACE FUNCTION test_func(id int, name varchar(10), out_id out int, out_name out varchar(10))
    AS $body$
    BEGIN
          out_id := id + 1;
          out_name := name;
    end
    $body$
    LANGUAGE PLPGSQL;

    次に、SELECT * FROM test_func(1,'1') INTO rec; ステートメントを実行して、recから対応するフィールドの戻り値を取得します。

  • 文字列接続の変数に含まれる引用符 (')

    次の例では、変数param2はSTRINGデータ型です。 たとえば、この変数の値はadb-'pgです。 AnalyticDB for PostgreSQLでsql_strを直接使用すると、ハイフン (-) が演算子として識別され、エラーが発生します。 変数を変換するには、quote_literal関数を使用する必要があります。

    例:

    sql_str := 'SELECT * FROM test1 WHERE col1 = ' || param1 || ' AND col2 = '''|| param2 || '''AND col3 = 3';

    変換結果:

    sql_str := 'SELECT * FROM test1 WHERE col1 = ' || param1 || ' AND col2 = '|| quote_literal(param2) || 'AND col3 = 3';
  • 2つのタイムスタンプ間の日数を取得する

    例:

    SELECT to_date('2019-06-30 16:16:16') - to_date('2019-06-29 15:15:15') + 1 INTO v_days FROM dual;

    変換結果:

    SELECT extract('days' from '2019-06-30 16:16:16'::timestamp - '2019-06-29 15:15:15'::timestamp + '1 days'::interval)::int INTO v_days;

PLデータ型

  • レコード

    AnalyticDB for PostgreSQLでRECORDデータ型を複合データ型に変換します。

    例:

    TYPE rec IS RECORD (a int, b int);

    変換結果:

    CREATE TYPE rec AS (a int, b int);
  • ネストテーブル

    • PLの変数として、NESTED TABLEデータ型はAnalyticDB for PostgreSQLのARRAYデータ型に変換できます。

      例:

      DECLARE
        TYPE Roster IS TABLE OF VARCHAR2(15);
        names Roster :=
        Roster('D Caruso', 'J Hamil', 'D Piro', 'R Singh');
      BEGIN
        FOR i IN names.FIRST .. names.LAST
        LOOP
            IF names(i) = 'J Hamil' THEN
              DBMS_OUTPUT.PUT_LINE(names(i));
            END IF;
        END LOOP;
      END;

      変換結果:

      CREATE OR REPLACE FUNCTION f1() RETURNS VOID AS
      $$
      
      DECLARE
          names varchar(15)[] := '{"D Caruso", "J Hamil", "D Piro", "R Singh"}';
          len int := array_length(names, 1);
      BEGIN
          for i in 1..len loop
              if names[i] = 'J Hamil' then
                  raise notice '%', names[i];
              end if;
          end loop;
          return ;
      END
      
      $$
       language 'plpgsql';
      
      SELECT f();
    • ネストされたテーブルが関数の戻り値として使用されている場合、テーブル関数を使用してネストされたテーブルを置き換えることができます。

  • 連想配列

    このデータ型の置き換えはできません。

  • 可変サイズ配列

    VARIABLE-SIZE ARRAYデータ型は、NESTED TABLEデータ型と同様に、ARRAYデータ型に変換できます。

  • グローバル変数

    AnalyticDB for PostgreSQLはグローバル変数をサポートしていません。 パッケージのすべてのグローバル変数を一時テーブルに格納し、グローバル変数の取得に使用する関数を定義できます。

    例:

    CREATE TEMPORARY TABLE global_variables (
            id int,
            g_count int,
            g_set_id varchar(50),
            g_err_code varchar(100)
    );
    
    INSERT INTO global_variables VALUES(0, 1, null, null);
    
    CREATE OR REPLACE FUNCTION get_variable() returns setof global_variables AS
    
    $$
    
    DECLARE
        rec global_variables%rowtype;
    BEGIN
        execute 'select * from global_variables' into rec;
        return next rec;
    END;
    
    $$
     LANGUAGE plpgsql;
    
    CREATE OR REPLACE FUNCTION set_variable(in param varchar(50), in value anyelement) returns void AS
    
    $$
    
    BEGIN
        execute 'update global_variables set ' ||  quote_ident(param) || ' = ' || quote_literal(value);
    END;
    
    $$
     LANGUAGE plpgsql;

    global_variables一时テーブルでは、IDフィールドはテーブルの配布キーです。 AnalyticDB for PostgreSQLでは、配布キーを変更することはできません。 テーブルにtmp_rec record; フィールドを追加する必要があります。

    グローバル変数を変更するには、select * from set_variable('g_error_code ', 'error'::varchar) into tmp_rec; ステートメントを実行します。

    グローバル変数を取得するには、select * from get_variable() into tmp_rec; error_code := tmp_rec.g_error_code; ステートメントを実行します。

SQL

  • CONNECT BY

    CONNECT BY句は、Oracleの階層クエリに使用できます。 AnalyticDB for PostgreSQLのSQL文を同じ方法で使用してCONNECT BY句を置き換えることはできません。 階層による循環トラバーサルを使用して、CONNECT by句を変換できます。

    例:

    CREATE TABLE employee(
           emp_id numeric(18),
           lead_id numeric(18),
           emp_name varchar(200),
           salary numeric(10,2),
           dept_no varchar(8)
    );
    INSERT INTO employee values('1',0,'king','1000000.00','001');
    INSERT INTO employee values('2',1,'jack','50500.00','002');
    INSERT INTO employee values('3',1,'arise','60000.00','003');
    INSERT INTO employee values('4',2,'scott','30000.00','002');
    INSERT INTO employee values('5',2,'tiger','25000.00','002');
    INSERT INTO employee values('6',3,'wudde','23000.00','003');
    INSERT INTO employee values('7',3,'joker','21000.00','003');
    INSERT INTO employee values('3',7,'joker','21000.00','003');
    SELECT emp_id,lead_id,emp_name,prior emp_name as lead_name,salary
         FROM employee
         START WITH  lead_id=0
         CONNECT BY prior emp_id =  lead_id

    変換結果:

    CREATE OR REPLACE FUNCTION f1(tablename text, lead_id int, nocycle boolean) RETURNS setof employee AS
    $$
    
    DECLARE
        idx int := 0;
        res_tbl varchar(265) := 'result_table';
        prev_tbl varchar(265) := 'tmp_prev';
        curr_tbl varchar(256) := 'tmp_curr';
    
        current_result_sql varchar(4000);
        tbl_count int;
    
        rec record;
    BEGIN
    
        execute 'truncate ' || prev_tbl;
        execute 'truncate ' || curr_tbl;
        execute 'truncate ' || res_tbl;
        loop
            -- Query the current hierarchical result and insert the result into the tmp_curr table.
            current_result_sql := 'insert into ' || curr_tbl || ' select t1.* from ' || tablename || ' t1';
    
            if idx > 0 then
                current_result_sql := current_result_sql || ', ' || prev_tbl || ' t2 where t1.lead_id = t2.emp_id';
            else
                current_result_sql := current_result_sql || ' where t1.lead_id = ' || lead_id;
            end if;
            execute current_result_sql;
    
            -- If a loop exists, delete the data that is traversed.
            if nocycle is false then
                execute 'delete from ' || curr_tbl || ' where (lead_id, emp_id) in (select lead_id, emp_id from ' || res_tbl || ') ';
            end if;
    
            -- Exit if no data exists.
            execute 'select count(*) from ' || curr_tbl into tbl_count;
            exit when tbl_count = 0;
    
            -- Save data from the tmp_curr table to the result table.
            execute 'insert into ' || res_tbl || ' select * from ' || curr_tbl;
            execute 'truncate ' || prev_tbl;
            execute 'insert into ' || prev_tbl || ' select * from ' || curr_tbl;
            execute 'truncate ' || curr_tbl;
            idx := idx + 1;
        end loop;
    
        -- The following information is returned:
        current_result_sql := 'select * from ' || res_tbl;
        for rec in execute current_result_sql loop
            return next rec;
        end loop;
        return;
    END
    
    $$
     language plpgsql;
  • ROWNUM

    1. ROWNUMを使用して、結果セットのサイズを制限できます。 ROWNUMを置き換えるには、LIMIT句を使用できます。

      例:

      SELECT * FROM t WHERE rownum < 10;

      変換結果:

      SELECT * FROM t LIMIT 10;
    2. row_number() over() を使用してROWNUMを生成します。

      例:

      SELECT rownum, * FROM t;

      変換結果:

      SELECT row_number() over() AS rownum, * FROM t;
  • DUALテーブル

    1. DUALテーブルを削除します。

      例:

      SELECT sysdate FROM dual;

      変換結果:

      SELECT current_timestamp;
    2. dualという名前のテーブルを作成します。

  • SELECTステートメントのユーザー定義関数

    AnalyticDB for PostgreSQLでは、SELECTステートメントでユーザー定義関数を呼び出すことができます。 これらの関数にSQL文を含めることはできません。 ユーザー定義関数にSQL文が含まれている場合、次のエラーメッセージが表示されます。

    ERROR: function cannot execute on segment because it accesses relation "public.t2" (functions.c:155) (seg1 slice1 127.0.0.1:25433 pid=52153) (cdbdisp.c:1326)
    DETAIL:
    SQL statement "select b from t2 where a = $1 "

    このエラーを防ぐには、SELECTステートメントのユーザー定義関数をSQL式またはサブクエリに変換します。

    例:

    CREATE OR REPLACE FUNCTION f1(arg int) RETURN int IS
        v int;
    BEGIN
        SELECT b INTO v FROM t2 WHERE a = arg;
        RETURN v;
    END;
    
    SELECT  a, f1(b) FROM t1;

    変換結果:

    SELECT t1.a, t2.b FROM t1, t2 WHERE t1.b = t2.a;
  • 複数のテーブルのOUTER JOIN (+)

    AnalyticDB for PostgreSQLは (+) 構文をサポートしていません。 (+) 構文を標準のOUTER JOIN構文に変換する必要があります。

    例:

    SELECT * FROM a,b WHERE a.id=b.id(+)

    変換結果:

    SELECT * FROM a LEFT JOIN b ON a.id=b.id

    (+) 構文で3つのテーブルに対してJOIN操作を実行する必要がある場合は、WTEを使用して2つのテーブルを結合し、WTEテーブルと (+) で接続されているテーブルに対してOUTER join操作を実行します。

    例:

    SELECT * FROM test1 t1, test2 t2, test3 t3 WHERE t1.col1(+) BETWEEN NVL(t2.col1, t3.col1) ADN NVL(t3.col1, t2.col1);

    変換結果:

    WITH cte AS (SELECT t2.col1 AS low, t2.col2, t3.col1 AS high, t3.col2 AS c2 FROM t2, t3)
    SELECT * FROM t1 RIGHT OUTER JOIN cte ON t1.col1 BETWEEN coalesce(cte.low, cte.high) AND coalesce(cte.high,cte.low);
  • MERGE INTO

    ほとんどの場合、MERGE INTO構文はINSERT ON CONFLICTによって実装できます。 ただし、MERGE INTOの一部の機能は、ストアドプロシージャによってのみ実装できます。

    INSERT ON CONFLICTの詳細については、「INSERT ON CONFLICTを使用したデータの上書き」をご参照ください。

    ストアドプロシージャの詳細については、「ストアドプロシージャ」をご参照ください。

  • シーケンス

    例:

    CREATE SEQUENCE seq1;
    SELECT seq1.nextval FROM dual;

    変換結果:

    CREATE SEQUENCE seq1;
    SELECT nextval('seq1');
  • カーソル

    • 次のステートメントを使用して、Oracleのカーソルをトラバースできます。

      例:

      FUNCTION test_func() IS
          Cursor data_cursor IS SELECT * from test1;
      BEGIN
          FOR I IN data_cursor LOOP
              Do something with I;
      END LOOP;
      END;

      変換結果:

      CREATE OR REPLACE FUNCTION test_func()
      AS $body$
      DECLARE
      data_cursor cursor for select * from test1;
      I record;
      BEGIN
          Open data_cursor;
          LOOP
             Fetch data_cursor INTO I;
            If not found then
                  Exit;
            End if;
            Do something with I;
          END LOOP;
          Close data_cursor;
      END;
      $body$
      LANGUAGE PLPGSQL;
    • 同じ名前のカーソルは、再帰関数で開くことができます。 これはAnalyticDB for PostgreSQLではサポートされていません。 FOR I INクエリを使用する必要があります。

      例:

      FUNCTION test_func(level IN numer) IS
          Cursor data_cursor IS SELECT * from test1;
      BEGIN
      If level > 5 then
              return;
         End if;
      
          FOR I IN data_cursor LOOP
              Do something with I;
              test_func(level + 1);
      END LOOP;
      END;

      変換結果:

      CREATE OR REPLACE FUNCTION test_func(level int) returns void
      AS $body$
      DECLARE
      data_cursor cursor for select * from test1;
      I record;
      BEGIN
          If level > 5 then
              return;
          End if;
          For I in select * from test1 LOOP
            Do something with I;
             PERFORM test_func(level+1);
          END LOOP;
      END;
      $body$
      LANGUAGE PLPGSQL;