Oracle® から Cloud SQL for PostgreSQL への移行: クエリ、ストアド プロシージャ、関数、トリガー

このドキュメントは、Oracle® 11g/12c データベースから Cloud SQL for PostgreSQL バージョン 12 への移行を計画し、実施する際に必要な情報とガイダンスを提供するシリーズの一つです。このシリーズには、最初の設定のパートに加えて、次のパートが含まれています。

クエリ

Oracle と Cloud SQL for PostgreSQL は ANSI SQL 標準に対応しています。そのため、一般的に SQL ステートメントの移行は難しくありません、基本的な構文要素を使用するだけで移行できます。スカラー関数やその他の Oracle 拡張機能を指定する必要はありません。以下では、一般的な Oracle クエリ要素とそれに対応する Cloud SQL for PostgreSQL の同等機能について説明します。

基本的な SELECT 構文と FROM 構文

Oracle の機能名または構文名 Oracle の概要または実装 Cloud SQL for PostgreSQL のサポート Cloud SQL for PostgreSQL の対応ソリューションまたは代替ソリューション
データ取得用の SQL 基本構文 SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
SELECT
(出力用)
SELECT 1 FROM DUAL SELECT 1
列のエイリアス SELECT COL1 AS C1 SELECT COL1 AS C1
OR
SELECT COL1 C1
テーブル名での大文字と小文字の区別 大文字と小文字は区別しない
(例: テーブル名として ordersORDERS のどちらも使用可能)
引用符で囲まない限り、名前は大文字と小文字が区別されません(たとえば、ordersORDERS は同じ、"orders" "ORDERS" は異なるものと扱われます)。

Cloud SQL for PostgreSQL の SELECT 構文の詳細については、ドキュメントをご覧ください。

インライン ビュー

  • インライン ビュー(別名、派生テーブル)は FROM 句に指定される SELECT ステートメントで、サブクエリとして使用されます。
  • インライン ビューを利用して複合計算を削除したり、結合オペレーションを排除したりすると、複雑なクエリをシンプルにできます。また、複数の個別クエリを 1 つの簡素化されたクエリに要約することもできます。
  • 変換に関する注記: Oracle ではインライン ビューにエイリアスを使用する必要はありませんが、Cloud SQL for PostgreSQL ではインライン ビューごとに固有のエイリアスが必要です。

次の表に、Oracle から Cloud SQL for PostgreSQL へのインライン ビューの変換例を示します。

Oracle 11g / 12c Cloud SQL for PostgreSQL 12
SQL> SELECT FIRST_NAME,
DEPARTMENT_ID,
SALARY,
DATE_COL
FROM EMPLOYEES,
(SELECT SYSDATE AS DATE_COL FROM DUAL);


出力は次のようになります。

FIRST_NAME DEPARTMENT_ID SALARY DATE_COL
-------------------- ------------- ---------- ---------
Steven 90 24000 30-JUL-19
Neena 90 17000 30-JUL-19
Lex 90 17000 30-JUL-19

インライン ビューにエイリアスがない場合:

postgres=> SELECT FIRST_NAME,
postgres-> DEPARTMENT_ID,
postgres-> SALARY,
postgres-> DATE_COL
postgres-> FROM EMPLOYEES, (SELECT NOW() AS DATE_COL);

ERROR: subquery in FROM must have an alias
LINE 5: FROM EMPLOYEES, (SELECT NOW() AS DATE_COL);

HINT: For example, FROM (SELECT ...) [AS] foo.

インライン ビューにエイリアスを追加した場合:

postgres=> SELECT FIRST_NAME,
postgres-> DEPARTMENT_ID,
postgres-> SALARY,
postgres-> DATE_COL
postgres-> FROM EMPLOYEES, (SELECT NOW() AS DATE_COL) AS C1;

出力は次のようになります。

first_name | department_id | salary | date_col
-------------+---------------+----------+--------------------------------
Steven | 90 | 24000.00 | 10/16/2020 08:35:18.470089 UTC
Neena | 90 | 17000.00 | 10/16/2020 08:35:18.470089 UTC
Lex | 90 | 17000.00 | 10/16/2020 08:35:18.470089 UTC

JOIN ステートメント

Oracle の JOIN ステートメントは、Cloud SQL for PostgreSQL の JOIN ステートメントでサポートされています。ただし、Oracle の結合演算子 (+) の使用は Cloud SQL for PostgreSQL でサポートされていません。同じ結果を得るには、外部結合用の標準 SQL 構文に変換する必要があります。

次の表に、JOIN の変換例を示します。

Oracle の JOIN の種類 Cloud SQL for PostgreSQL でのサポート Cloud SQL for PostgreSQL JOIN の構文
INNER JOIN SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
CROSS JOIN SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E CROSS JOIN DEPARTMENTS D;
FULL JOIN [ OUTER ] SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E FULL JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
LEFT JOIN [ OUTER ] SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E LEFT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
RIGHT JOIN [ OUTER ] SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E RIGHT JOIN DEPARTMENTS D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;
SUBQUERY SELECT E.FIRST_NAME, D.DEPARTMENT_NAME
FROM EMPLOYEES E JOIN (SELECT * FROM DEPARTMENTS)D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;

UNION、UNION ALL、INTERSECT、MINUS

Cloud SQL for PostgreSQL は、Oracle UNIONUNION ALL、および INTERSECT 演算子をサポートしています。MINUS 演算子はサポートされていません。ただし、Cloud SQL for PostgreSQL は EXCEPT 演算子を実装しています。この演算子は Oracle の MINUS 演算子と同等です。また、Cloud SQL for PostgreSQL は、Oracle ではサポートされていない INTERSECT ALL 演算子と EXCEPT ALL 演算子をサポートしています。

  • UNION: 2 つ以上の SELECT ステートメントの結果セットを結合しますが、重複するレコードは除外します。
  • UNION ALL: 重複レコードを除外せずに、複数の SELECT ステートメントの結果セットを結合します。
  • INTERSECT: レコードが両方のデータセットに存在する場合にのみ、2 つ以上の SELECT ステートメントの結果で共通する部分を返します。重複するレコードは除外されません。
  • INTERSECT ALL(Cloud SQL for PostgreSQL のみ): レコードが両方のデータセットに存在する場合にのみ、2 つ以上の SELECT ステートメントの結果で共通する部分を返します。
  • MINUS (EXCEPT Cloud SQL for PostgreSQL): 2 つ以上の SELECT ステートメントを比較し、最初のクエリで他のステートメントから返されない個別の行のみを返します。
  • EXCEPT ALL(Cloud SQL for PostgreSQL のみ): 2 つ以上の SELECT ステートメントを比較し、重複レコードを排除せずに最初のクエリで他のステートメントから返されない行のみを返します。

変換に関する注記

Oracle の MINUS 演算子を Cloud SQL for PostgreSQL に変換する場合は、EXCEPT 演算子を使用します。

Oracle の関数 Oracle の実装 Cloud SQL for PostgreSQL のサポート Cloud SQL for PostgreSQL の対応ソリューションまたは代替ソリューション
UNION SELECT COL1 FROM TBL1
UNION
SELECT COL1 FROM TBL2
SELECT COL1 FROM TBL1
UNION
SELECT COL1 FROM TBL2
UNION ALL SELECT COL1 FROM TBL1
UNION ALL
SELECT COL1 FROM TBL2
SELECT COL1 FROM TBL1
UNION ALL
SELECT COL1 FROM TBL2
INTERSECT SELECT COL1 FROM TBL1
INTERSECT
SELECT COL1 FROM TBL2
SELECT COL1 FROM TBL1
INTERSECT
SELECT COL1 FROM TBL2
MINUS SELECT COL1 FROM TBL1
MINUS
SELECT COL1 FROM TBL2
○(PostgreSQL では Convert MINUS から EXCEPT SELECT COL1 FROM TBL1
EXCEPT
SELECT COL1 FROM TBL2

スカラー(単一行)関数とグループ化関数

Cloud SQL for PostgreSQL には、さまざまなスカラー(単一行)関数と集計関数が用意されています。一部の Cloud SQL for PostgreSQL 関数は、対応する Oracle 関数に非常によく似ています(名前と機能が似ている関数や、名前は異なっていても機能が似ている関数などがあります)。Cloud SQL for PostgreSQL の関数によっては、Oracle での対応する関数名と同じ名前が使用されていても、機能がそれぞれ異なる場合もあります。

次の表に、Oracle と Cloud SQL for PostgreSQL の間で名前と機能が同じ関数(「○」で示しています)と、変換が推奨される関数(「○」以外)を示します。

文字関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
CONCAT str1 と str2 を連結した文字列を返します。

CONCAT('A', 1) = A1
あり CONCAT Oracle と同等。

CONCAT('A', 1) = A1
LOWER/UPPER すべての文字を小文字または大文字にして返します。

LOWER('SQL') = sql
あり LOWER/UPPER Oracle と同等。

LOWER('SQL') = sql
LPAD/RPAD expr1 の左側または右側に、expr2 で指定した文字を連続的に埋め込んで n 桁にして返します。:

LPAD('A',3,'*') = **A
あり LPAD/RPAD Oracle と同等。

LPAD('A',3,'*') = **A
SUBSTR char の一部分(文字位置で始まり、部分文字列の長さ)を返します。


SUBSTR('PostgreSQL', 8, 3)
= SQL
部分的 SUBSTR 開始位置が正の数である場合の Oracle と同等です。

SUBSTR('PostgreSQL', 8, 3)
= SQL

Oracle で負の数が開始位置として指定されている場合、文字列の最後から部分文字列演算を実行します。これは Cloud SQL for PostgreSQL とは異なります。Oracle の動作が必要な場合は、代わりに RIGHT 関数を使用します。
INSTR 指定した文字列の中にある特定の文字列の位置(インデックス)を返します。

INSTR('PostgreSQL', 'e')
= 7
なし なし Cloud SQL for PostgreSQL には組み込みの instr 関数はありません。Oracle 互換の instr 関数は、PL/pgSQL を使用して実装できます。
REPLACE 検索文字列を置換文字列で置き換えた char を返します。


REPLACE('ORADB', 'ORA', 'PostgreSQL')
= PostgreSQLDB
部分的 REPLACE Oracle では置換文字列パラメータはオプションですが、Cloud SQL for PostgreSQL では必須です。パラメータを省略すると、検索文字列のオカレンスはすべて削除されます。Cloud SQL for PostgreSQL では、置換文字列に空の文字列を指定すると同じ動作を実現できます。

REPLACE('ORADB', 'ORA', 'PostgreSQL')
= PostgreSQLDB
TRIM 文字列から先頭または末尾(あるいは両方)の文字を削除します。

TRIM(both '-' FROM '-PostgreSQL-')
= PostgreSQL
TRIM(' PostgreSQL ')
= PostgreSQL
あり TRIM Oracle と同等。

TRIM(both '-' FROM '-PostgreSQL-')
= PostgreSQL
TRIM(' PostgreSQL ')
= PostgreSQL
LTRIM/RTRIM 文字列の左端または右端から、検索で指定されたすべての文字を削除します。


LTRIM(' PostgreSQL', ' ')
= PostgreSQL
あり LTRIM/RTRIM Oracle と同等。

LTRIM(' PostgreSQL', ' ') = PostgreSQL
ASCII データベースの文字セットに含まれる最初の文字の 10 進表現を返します。

ASCII('A') = 65
あり ASCII Oracle と同等。

ASCII('A') = 65
CHR 文字に対応する ASCII コード値(0~225 の数値)を返します。

CHR(65) = A
あり CHAR Oracle と同等。

CHR(65) = A
LENGTH 指定した文字列の長さを返します。

LENGTH ('PostgreSQL') = 10
あり LENGTH Oracle と同等。

LENGTH ('PostgreSQL') = 10
REGEXP_REPLACE 正規表現パターンに一致する文字列を検索します。

REGEXP_REPLACE('John', '[hn].', '1') = Jo1
あり REGEXP_REPLACE Oracle と同等。

REGEXP_REPLACE('John', '[hn].', '1') = Jo1
REGEXP_SUBSTR 正規表現パターンに一致する文字列を検索できるように、
SUBSTR 関数の機能を拡張したものです。

REGEXP_SUBSTR('https://console.cloud.google.com/sql/instances','https://([[:alnum:]]+\.?){3,4}/?')
= https://console.cloud.google.com/
なし なし 同様の機能を実現するには、PostgreSQL の REGEXP_MATCH を使用します。
REGEXP_COUNT ソース文字列でのパターン出現回数を返します。 × なし 同様の機能を実現するには、PostgreSQL の REGEXP_MATCH を使用します。
REGEXP_INSTR 正規表現パターンに一致する文字列の位置(インデックス)を検索します。
× なし この機能をアプリケーション レイヤに変換します。
REVERSE 文字列を反転させて返します。

REVERSE('PostgreSQL') = LQSergtsoP
あり REVERSE Oracle と同等。

REVERSE('PostgreSQL') = LQSergtsoP
数値関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
ABS n の絶対値を返します。

ABS(-4.6) = 4.6
あり ABS Oracle と同等。

ABS(-4.6) = 4.6
CEIL n 以上の最小の整数を返します。

CEIL(21.4) = 22
あり CEIL Oracle と同等。

CEIL(21.4) = 22
FLOOR n 以下の最大の整数を返します。

FLOOR(-23.7) = -24
あり FLOOR Oracle と同等。

FLOOR(-23.7) = -24
MOD mn で割った余りを返します。

MOD(10, 3) = 1
あり MOD Oracle と同等。

MOD(10, 3) = 1
ROUND 小数点以下 n 桁に丸めた数値を返します。

ROUND(1.39, 1) = 1.4
あり ROUND Oracle と同等。

ROUND(1.39, 1) = 1.4
TRUNC
(数値)
n1 を小数点以下 n2 桁に切り捨てた数値を返します。

TRUNC(99.999) = 99
TRUNC(99.999, 0) = 99
あり TRUNCATE
(数値)
Oracle と同等。

TRUNC(99.999) = 99
TRUNC(99.999, 0) = 99
DateTime 関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
SYSDATE データベース サーバーが存在するオペレーティング システムに設定されている現在の日付と時刻を返します。

SELECT SYSDATE FROM DUAL
= 31-JUL-2019
部分的(関数名と形式が異なる) CURRENT_TIMESTAMP CURRENT_TIMESTAMP は、Oracle の SYSDATE 関数とは異なる形式の日時を返します。

SELECT CURRENT_TIMESTAMP
= 2019-07-31 06:46:40.171477+00
SYSTIMESTAMP 小数点以下の秒とタイムゾーンを含む、システムの日付を返します。

SELECT SYSTIMESTAMP FROM DUAL
= 01-JAN-19 07.37.11.622187000 AM +00:00
関数名の一部が異なる CURRENT_TIMESTAMP Cloud SQL for PostgreSQL は、Oracle とは異なる日付 / 時刻形式を返します。日付の形式は、元の日付 / 時刻形式と一致させる必要があります。

SELECT CURRENT_TIMESTAMP
= 2019-01-31 07:37:11.622187+00
LOCAL TIMESTAMP セッションのタイムゾーンでの現在の日付と時刻を TIMESTAMP データ型の値で返します。

SELECT LOCALTIMESTAMP FROM DUAL
= 01-JAN-19 10.01.10.123456 PM
部分的(日時形式が異なる) LOCAL TIMESTAMP Cloud SQL for PostgreSQL は、Oracle とは異なる日付 / 時刻形式を返します。日付の形式は、元の日付 / 時刻形式と一致させる必要があります。

SELECT LOCALTIMESTAMP
= 2019-01-31 07:37:11.622187+00
CURRENT_DATE セッションのタイムゾーンでの現在の日付を返します。

SELECT CURRENT_DATE FROM DUAL
= 31-JAN-19
部分的(日時形式が異なる) CURRENT_ DATE Cloud SQL for PostgreSQL は、Oracle とは異なる日付 / 時刻形式を返します。日付の形式は、元の日付 / 時刻形式と一致させる必要があります。

SELECT CURRENT_DATE
= 2019-01-31
CURRENT_TIMESTAMP セッションのタイムゾーンでの現在の日付と時刻を返します。

SELECT CURRENT_TIMESTAMP FROM DUAL
= 31-JAN-19 06.54.35.543146 AM +00:00
部分的(日時形式が異なる) CURRENT_TIMESTAMP Cloud SQL for PostgreSQL は、Oracle とは異なる日時形式を返します。日付の形式は、元の日時形式と一致する必要があります。

SELECT CURRENT_TIMESTAMP FROM DUAL
= 2019-01-31 07:37:11.622187+00s
ADD_MONTHS 日付と、月を表す整数を返します。

ADD_MONTHS(SYSDATE, 1)
= 31-JAN-19
なし なし Cloud SQL for PostgreSQL で同じ機能を実現するには、+ / - 演算子を使用して時間間隔を指定します。

SELECT CURRENT_TIMESTAMP + INTERVAL '1 MONTH'
= 2019-01-31 07:37:11.622187+00s
EXTRACT
(日付部分)
日付 / 時刻または期間の式から、指定された日付 / 時刻フィールドの値を返します。

EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
あり EXTRACT
(日付部分)
Oracle と同等。

EXTRACT(YEAR FROM DATE '2019-01-31')
= 2019
LAST_DAY 指定された日付を含む月の最終日の日付を返します。

LAST_DAY('01-JAN-2019')
= 31-JAN-19
なし なし この問題を回避するには、DATE_TRUNC 演算子と + 演算子を使用して月の最終日を計算します。日付の形式は元の日付 / 時刻形式と一致させる必要があります。

SELECT DATE_TRUNC('MONTH', DATE '01-JAN-2019') + INTERVAL '1 MONTH -1 DAY'
= 2019-01-31
MONTH_BETWEEN date1 と date2 の間の月数を返します。

MONTHS_BETWEEN(SYSDATE, SYSDATE-60)
= 1.96
部分的

(日時形式が異なる関数)
AGE Cloud SQL for PostgreSQL の AGE 関数は、2 つのタイムスタンプ間の間隔を返します。

AGE(DATE '01-JAN-2019', DATE '01-JAN-2019' - 60)
= 1 mon 29 days

Oracle の MONTH_BETWEEN 関数と同じ値を実現するには、より具体的な変換が必要になります。
TO_CHAR(日付 / 時刻) 日付形式で指定された形式で、日時またはタイムスタンプのデータ型を VARCHAR2 データ型の値に変換します。


TO_CHAR(SYSDATE,'DD-MM-YYYY HH24:MI:SS')
= 01-01-2019 10:01:01
あり To_CHAR Oracle と同等。

TO_CHAR(CURRENT_TIMESTAMP,'DD-MM-YYYY HH24:MI:SS');
01-01-2019 10:01:01
エンコード関数とデコード関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
DECODE IF-THEN-ELSE ステートメントを使用して、各検索値を 1 つずつ式と比較します × CASE 同様の機能を実現するには、Cloud SQL for PostgreSQL の CASE ステートメントを使用します。
DUMP データ型のコード、長さ(バイト数)、式の内部表現を含む VARCHAR2 値を返します。 × なし サポートされていません。
ORA_HASH 指定した式のハッシュ値を計算します。 × MD5 / SHA224 / SHA256 / SHA385 / SHA512 ハッシュ値を生成するには、128 ビットのチェックサムに Cloud SQL for PostgreSQL の MD5 関数を使用するか、160 ビットのチェックサムに SHA 関数を使用します。
変換関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
CAST 1 つの組み込みデータ型または集合型の値を別の組み込みデータ型または集合型の値に変換します。

CAST('1' as int) + 1
= 2
部分的 CAST Cloud SQL for PostgreSQL の CAST 関数は、Oracle の CAST 関数と同様ですが、2 つのデータベース間でのデータ型の違いにより、調整が必要になることがあります。

CAST('1' as int) + 1
= 2
CONVERT 文字列をある文字セットから別の文字セットに変換します。

CONVERT ( 'Ä Ê Í Õ Ø A B C D E ', 'US7ASCII', 'WE8ISO8859P1')
= ?? ?? ?? A B C
部分的 CONVERT Cloud SQL for PostgreSQL の CONVERT 関数は bytea 値を返します。これは、VARCHAR または TEXT ではなく、バイナリ文字列です。PostgreSQL でサポートされている文字セットも Oracle とは異なります。

CONVERT('Ä Ê Í Õ Ø A B C D E', 'UTF8', 'LATIN1')
= [Binary representation of the string in LATIN1 encoding]
TO_CHAR
(string/numeric)
この関数は数値または日付を文字列に変換します。

TO_CHAR(22.73,'$99.9')
= $22.7
部分的 TO_CHAR Cloud SQL for PostgreSQL の TO_CHAR 関数は、Oracle と同様の機能です。Cloud SQL for PostgreSQL がサポートする書式設定文字列のリストは少し異なります。デフォルトでは、Cloud SQL for PostgreSQL は符号の列を 1 つ予約するため、正数の前にスペースが挿入されます。これは、FM 接頭辞を使用して抑制できます。

TO_CHAR(22.73,'FM$99.9')
= $22.7
TO_DATE Oracle の TO_DATE 関数は、文字列をソース固有の日付 / 時刻形式の日付に変換します。

TO_DATE('2019/01/01', 'yyyy-mm-dd')
= 01-JAN-2019
部分的 TO_DATE Cloud SQL for PostgreSQL の TO_DATE 関数は、Oracle と同様の機能です。Cloud SQL for PostgreSQL がサポートする書式設定文字列のリストは少し異なります。

TO_DATE('2019/01/01', 'yyyy-mm-dd')
= 2019-01-01
TO_NUMBER 式を NUMBER データ型の値に変換します。

TO_NUMBER('01234')
= 1234
部分的 TO_NUMBER Cloud SQL for PostgreSQL の TO_NUMBER 関数では入力として書式設定文字列が必要ですが、Oracle では省略可能です。

TO_NUMBER('01234','99999')
= 1234

代替案として、複雑な書式設定文字列を必要としない変換に CAST 関数を使用する方法があります。

CAST('01234' AS NUMERIC)
= 1234
条件付き SELECT 関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
CASE CASE ステートメントは、一連の条件に基づいて対応するステートメントを選択して実行します。
構文は次のとおりです。

CASE WHEN condition THEN result [WHEN ...] [ELSE result] END
あり CASE Oracle と同等。

CASE WHEN condition THEN result [WHEN ...] [ELSE result] END
null 関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
COALESCE 式のリスト内の最初の null 以外の式を返します。

COALESCE(null, '1', 'a')
= a
あり COALESCE Oracle と同等。

COALESCE(null, '1', 'a')
= 1
NULLIF expr1 と expr2 を比較します。同じ式である場合は null を返します。同じ式ではない場合は、expr1 を返します。

NULLIF('1', '2')
= 1
あり NULLIF Oracle と同等。

NULLIF('1', '2')
= 1
NVL (空白として返された)null を、クエリ結果に含まれる文字列で置き換えます。

NVL(null, 'a')
= a
なし COALESCE 代わりに COALESCE 関数を使用します。

COALESCE(null, 'a')
= a
NVL2 指定された式が null または null 以外であるかどうかによって、クエリで返す値を決定します。
なし COALESCE 代わりに COALESCE 関数を使用します。

COALESCE(null, 1, 'a')
= 1
環境関数と ID 関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
SYS_GUID 最大 16 バイトからなる、グローバルに一意の ID(RAW 値)を生成して返します。


SELECT SYS_GUID() FROM DUAL
= 8EFA4A31468B4C6DE05011AC0200009E
部分的(関数名と形式が異なる) UUID_GENERATE_V4 Cloud SQL for PostgreSQL は、uuid-ossp 拡張機能をサポートします。これは UUID_GENERATE_V4 のような関数を生成する UUID のリストを提供します。

SELECT UUID_GENERATE_v4()
= eaf356a6-2847-478d-af3b-6883f5ac6af2
UID セッション ユーザー(ログオンしているユーザー)を
一意に識別する整数を返します。

SELECT UID FROM DUAL
= 43
なし なし なし
USER 現在のセッション ユーザー名を返します。

SELECT USER FROM DUAL
= UserName
あり USER Oracle と同等。

SELECT USER;
= postgres
USERENV 現在のユーザー セッションに関する情報と現在のパラメータ構成を返します。

SELECT USERENV('LANGUAGE') FROM DUAL
= ENGLISH_AMERICA.AL32UTF8
なし なし Cloud SQL for PostgreSQL には同等の USERENV 関数はありませんが、USERENV('SID') などの個々のパラメータは、PG_BACKGROUND_PID() のようなシステム情報関数を使用して取得できます。
ROWID Oracle サーバーは各テーブルの行ごとに、テーブル内でその行を識別する一意の ROWID を割り当てます。ROWID は行のアドレスであり、データ オブジェクト番号、行のデータブロック、行の位置、データファイルからなります。 関数名の一部が異なる ctid Cloud SQL for PostgreSQL の ctid は、テーブル内の行バージョンの物理的な場所を識別します。これは、Oracle の ROWID と類似した機能です。
ROWNUM Oracle によりテーブルまたは結合テーブルから行が選択される順番を表す数値を返します。 × LIMIT or ROW_NUMBER() Cloud SQL for PostgreSQL は、ROWNUM を使用してクエリにより返される結果の数を制限するのではなく、同様の目的で LIMITOFFSET をサポートします。

他のシナリオでは、Oracle の ROWNUM に代わる回避策として、ROW_NUMBER() ウィンドウ関数を使用できます。ただし、結果の順序とパフォーマンスの差分を検討してから代わりとして使用する必要があります。
集計(グループ化)関数
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
AVG 列または式の平均値を返します AVG Oracle と同等
COUNT クエリによって返される行数を返します。 COUNT Oracle と同等
COUNT (DISTINCT) 列または式に含まれる固有の値の数を返します。 COUNT
(DISTINCT)
Oracle と同等
MAX 列または式の最大値を返します。 MAX Oracle と同等
MIN 列または式の最小値を返します。 MIN Oracle と同等
SUM 列または式の値の合計を返します。 SUM Oracle と同等
LISTAGG 測定列の各グループに含まれる値を連結して、ORDER BY 句で指定された単一行でグループ内のデータを表示します。

SELECT LISTAGG(
DEPARTMENT_NAME, ', ')
WITHIN GROUP
(ORDER BY DEPARTMENT_NAME) DEPT
FROM DEPARTMENTS;

-- Single line results
= Accounting, Administration, Benefits, Construction
なし STRING_AGG Cloud SQL for PostgreSQL の STRING_AGG 関数を使用して、Oracle と同様の結果を返します。ただし、以下の場合は構文が異なります。

SELECT STRING_AGG(DEPARTMENT_NAME, ', ' order by DEPARTMENT_NAME) FROM DEPARTMENTS;

-- Single line results
= Accounting, Administration, Benefits, Construction
Oracle 12c Fetch
Oracle の関数 Oracle 関数の仕様または実装 Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL の対応関数 Cloud SQL for PostgreSQL の関数の仕様または実装
FETCH 複数行クエリの結果セットからデータ行を取得します。

SELECT * FROM
EMPLOYEES
FETCH FIRST 10 ROWS ONLY;
なし LIMIT Cloud SQL for PostgreSQL の LIMIT 句を使用して、特定のレコードセットのみを取得します。

SELECT * FROM EMPLOYEES LIMIT 10;

基本的なフィルタリング、演算子、サブクエリ

基本的なフィルタリング、演算子関数、サブクエリは、最小限の追加の作業を行うだけで比較的簡単に変換できます。

変換に関する注記

デフォルトで返される日付形式は Oracle と Cloud SQL for PostgreSQL で異なるため、日付の形式を確認し、必要な処置を行う必要があります。

  • Oracle の SYSDATE 関数はデフォルトで 01-AUG-19 を返します。
  • PostgreSQL の CURRENT_DATE 関数はデフォルトで 2019-08-01 を返します(書式設定を行っても時刻は返されません)。現在の日時を取得するには、CURRENT_TIMESTAMP 関数を使用します。デフォルトでは、2019-08-01 00:00:00.000000+00 を返します。
  • 日付と時刻の形式は、Cloud SQL for PostgreSQL の TO_CHAR 関数で設定できます。
Oracle の関数またはサブクエリ Cloud SQL for PostgreSQL の同等機能 Cloud SQL for PostgreSQL で対応する関数またはサブクエリ Cloud SQL for PostgreSQL の関数の仕様または実装
EXISTS/ NOT EXISTS EXISTS/ NOT EXISTS SELECT * FROM DEPARTMENTS D
WHERE EXISTS (SELECT 1
FROM EMPLOYEES E
WHERE
E.DEPARTMENT_ID =
D.DEPARTMENT_ID);
IN/NOT IN IN/NOT IN SELECT * FROM DEPARTMENTS D
WHERE DEPARTMENT_ID IN
(SELECT DEPARTMENT_ID
FROM EMPLOYEES E);

-- OR
SELECT * FROM EMPLOYEES
WHERE (EMPLOYEE_ID, DEPARTMENT_ID)
IN((100, 90));
LIKE/NOT LIKE LIKE/NOT LIKE SELECT * FROM EMPLOYEES
WHERE FIRST_NAME LIKE '_e_n%';
BETWEEN/ NOT BETWEEN BETWEEN/
NOT BETWEEN
SELECT * FROM EMPLOYEES
WHERE EXTRACT(YEAR FROM HIRE_DATE)
NOT BETWEEN 2001 and 2004;
AND/OR AND/OR SELECT * FROM EMPLOYEES
WHERE DEPARTMENT_ID IN(100, 101)
AND (SALARY >= 1000 OR HIRE_DATE <= '2006-02-05');
SubQuery あり SubQuery Cloud SQL for PostgreSQL は、JOIN ステートメントおよび WHERE/AND 句のフィルタリングで、SELECT レベルのサブクエリをサポートしています。

-- SELECT SubQuery
SELECT D.DEPARTMENT_NAME,
(SELECT AVG(SALARY) AS AVG_SAL
FROM EMPLOYEES E
WHERE E.DEPARTMENT_ID =
D.DEPARTMENT_ID) AVG_SAL
FROM DEPARTMENTS D;

-- JOIN SubQuery
SELECT FIRST_NAME, LAST_NAME, SALARY
FROM EMPLOYEES E JOIN
(SELECT *
FROM DEPARTMENTS
WHERE LOCATION_ID = 2700) D
ON E.DEPARTMENT_ID = D.DEPARTMENT_ID;

-- Filtering Subquery
SELECT FIRST_NAME,
LAST_NAME,
SALARY
FROM EMPLOYEES
WHERE SALARY < (SELECT AVG(SALARY)
FROM EMPLOYEES);
演算子 演算子 Cloud SQL for PostgreSQL は、すべての基本演算子をサポートしています。

> | >= | < | <= | = | <> | !=

分析関数(またはウィンドウ関数とランキング関数)

Oracle の分析関数では、標準 SQL の分析関数の機能を拡張して、行のグループ(RANK()ROW_NUMBER()FIRST_VALUE() など)に基づいて集約値を計算できます。これらの関数は、1 つのクエリ式の範囲内で論理的に分割されたレコードに適用されます。一般に、データ ウェアハウジングとビジネス インテリジェンス レポートおよびアナリティクスを組み合わせて使用されます。

変換に関する注記

Cloud SQL for PostgreSQL は、Postgres で集計関数ウィンドウ関数として知られる多くの分析関数をサポートしています。Postgres でサポートされていないあまり一般的ではない関数を使用しているアプリケーションの場合、サポートされている拡張機能を探すか、ロジックをアプリケーション レイヤに移動する必要があります。

次の表に、Oracle で最も一般的な分析関数を示します。

関数ファミリー 関連する関数 Cloud SQL for PostgreSQL でのサポート
分析とランキング RANK
AVERAGE_RANK
DENSE_RANK
ROW_NUMBER
PERCENT_RANK
CUME_DIST
NTILE
FIRST_VALUE
LAST_VALUE
OVER (PARTITION BY...)
○(AVERAGE_RANK を除く)
階層表示 CONNECT BY
HIER_ANCESTOR
HIER_CHILD_COUNT
HIER_DEPTH
HIER_LEVEL
HIER_ORDER
HIER_PARENT
HIER_TOP
×
ラグ LAG
LAG_VARIANCE LAG_VARIANCE_PERCENT LEAD
LEAD_VARIANCE LEAD_VARIANCE_PERCENT
○(LAGLEAD のみ)

共通テーブル式(CTE)

CTE では、一連のコードのロジックを実装して、複雑すぎるか何度も使用するには効率的ではないと考えられる SQL コードを再利用できます。CTE に名前を付けた後、SQL ステートメントのさまざまな部分で WITH 句を使って CTE を複数回使用できます。CTE は、Oracle と Cloud SQL for PostgreSQL の両方でサポートされています。

Oracle と Cloud SQL for PostgreSQL
WITH DEPT_COUNT
(DEPARTMENT_ID, DEPT_COUNT) AS
(SELECT DEPARTMENT_ID,
COUNT(*)
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID)

SELECT E.FIRST_NAME ||' '|| E.LAST_NAME AS EMP_NAME,
D.DEPT_COUNT AS EMP_DEPT_COUNT
FROM EMPLOYEES E JOIN DEPT_COUNT D
USING (DEPARTMENT_ID)
ORDER BY 2 DESC;

MERGE ステートメント

MERGE(または UPSERT)ステートメントを使用すると、1 つの DML オペレーションを別個に実行するのではなく、1 つの MERGE オペレーションの中で条件付きで複数の DML オペレーションを実行する単一の SQL ステートメントを指定できます。ソーステーブルからレコードを選択した後、論理構造を指定することによって、ターゲット テーブルに対して複数の DML オペレーションを自動的に実行します。この機能を使用すると、挿入、更新、削除を何度も行う必要がありません。MERGE は確定的なステートメントです。つまり、MERGE ステートメントで行が処理された後、その行を同じ MERGE ステートメントで再処理することはできません。

変換に関する注記

Cloud SQL for PostgreSQL は、Oracle とは異なり、MERGE 機能をサポートしていません。Cloud SQL for PostgreSQL には、MERGE 機能を部分的にシミュレートするため、INSERT ... ON CONFLICT DO UPDATE ステートメントが用意されています。

  • INSERT… ON CONFLICT DO UPDATE: 挿入された行によって、固有の違反または除外制約違反を引き起こす場合は、ON CONFLICT DO UPDATE 句で指定された代替のアクションを実行します。たとえば、次のようになります。
INSERT INTO tbl (a,b,c) VALUES (1,2,3)
  ON CONFLICT (a) DO UPDATE SET b = 2, c = 3;

代わりに、MERGE 機能をストアド プロシージャに変換し、例外 / 重複の処理で INSERTUPDATEDELETE コマンドを使用して DML オペレーションを管理することもできます。

SQL ステートメントのヒント

Oracle では、クエリ実行計画の効率化を目的に、ユーザーが豊富な SQL クエリヒントを使用してオプティマイザーの動作に影響を与えられるようになっています。Cloud SQL for PostgreSQL には、オプティマイザーに影響を与えるような、同等の SQL ステートメント レベル、ヒンティング メカニズムはありません。

Cloud SQL for PostgreSQL は、クエリ プランナーによって選択されたクエリプランに影響を与えるため、セッション レベルで適用可能な構成パラメータのセットを提供します。これらの構成パラメータの影響は、特定のアクセス メソッドの有効化と無効化や、プランナーのコスト定数の調整などさまざまです。たとえば、次のステートメントは、テーブル全体のスキャンなどの、シーケンシャル スキャンのプランタイプをクエリ プランナーで使用できなくなります。

SET ENABLE_SEQSCAN=FALSE;

ランダム ディスクのページ取得(デフォルトは 4.0)のプランナーの費用の見積もりを調整するには、次のステートメントを使用します。

SET RANDOM_PAGE_COST=2.0;

この値を削減すると、Cloud SQL for PostgreSQL はインデックス スキャンを優先します。値を引き上げることで、逆の処理が行われます。

変換に関する注記

Oracle と Cloud SQL for PostgreSQL のオプティマイザーは根本的に異なります。Cloud SQL for PostgreSQL は Oracle スタイルの SQL クエリヒントをサポートしていないため、Cloud SQL for PostgreSQL への移行時にはクエリヒントはすべて削除することをおすすめします。次に、Cloud SQL for PostgreSQL ツールを使用して厳格なパフォーマンス テストを実施し、実行プランでクエリを調べて、ユースケースに応じてインスタンス パラメータまたはセッション パラメータを調整します。

実行計画

実行計画の主な目的は、クエリ オプティマイザーがデータベースのデータにアクセスする際に行った選択についての詳細を提供することです。クエリ オプティマイザーによって、データベース ユーザー用に SELECTINSERTUPDATEDELETE の各ステートメントの実行計画が生成されます。また、管理者は特定のクエリや DML オペレーションについての理解を深めることができます。これは、クエリのパフォーマンスを調整する場合に非常に有効です。たとえば、インデックスのパフォーマンスを確認する場合や、作成する必要があるインデックスがあるかどうかを判断する場合に役立ちます。

実行計画は、データ量、データ統計、インスタンス パラメータ(グローバル パラメータまたはセッション パラメータ)によって影響される可能性があります。

変換に関する考慮事項

実行計画は移行の必要があるデータベース オブジェクトではありません。これは、同じデータセットに対して同じステートメントを実行する場合に、Oracle と Cloud SQL for PostgreSQL の間のパフォーマンスの違いを分析するためのツールです。

Cloud SQL for PostgreSQL でサポートしている実行プランの構文、機能、出力は、Oracle とは異なります。

実行計画の例を次に示します。

Oracle の実行計画 Cloud SQL for PostgreSQL の実行計画
SQL> EXPLAIN PLAN FOR
SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105;

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY (FORMAT=>'ALL +OUTLINE'));

Plan hash value: 1833546154

---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 69 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 69 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
postgres=> EXPLAIN SELECT * FROM EMPLOYEES WHERE EMPLOYEE_ID = 105; QUERY PLAN -------------------------------------------------------------------------------- Index Scan using emp_emp_id_pk on employees (cost=0.14..8.16 rows=1 width=71) Index Cond: (employee_id = '105'::numeric) (2 rows)

ストアド プロシージャ、関数、トリガー

PL/SQL は Oracle の拡張プロシージャ言語であり、データベース内でコードベースのソリューションを作成、保管、適用するために使用されます。通常、データベースのストアド プロシージャと関数は、Oracle の PL/SQL、MySQL の MySQL プロシージャ言語などの ANSI SQL および SQL 拡張プロシーシャ言語からなるコード要素です。PL/pgSQL は PostgreSQL の拡張プロシージャ言語向けです。

これらのストアド プロシージャと関数の目的は、パフォーマンス、互換性、セキュリティなどの要件に応じて、アプリケーションからではなくデータベース内から実行するのに適したソリューションを提供することです。ストアド プロシージャと関数では両方とも PL/SQL を使用しますが、ストアド プロシージャは主に DDL/DML オペレーションを実行するために使用されます。関数は主に、計算を行って特定の結果を返すために使用されます。

PL/SQL から PL/pgSQL

Oracle PL/SQL から Cloud SQL for PostgreSQL への移行という観点では、PL/pgSQL の構造と構文は Oracle PL/SQL と類似しています。ただし、コードの移行が必要になる大きな違いがいくつかあります。たとえば、Oracle と Cloud SQL for PostgreSQL ではデータ型が異なります。多くの場合、Cloud SQL for PostgreSQL でサポートされるデータ型名が使用されるように、移行後のコードで変換が必要になります。この 2 つの言語の違いについては、Oracle PL/SQL からの移行をご覧ください。

コード オブジェクトの権限とセキュリティ

Oracle でストアド プロシージャまたは関数を作成するには、CREATE PROCEDURE システム権限が必要です(他のユーザーでプロシージャまたは関数を作成するには、CREATE ANY PROCEDURE 権限が必要です)。ストアド プロシージャまたは関数を実行するには、データベース ユーザーに EXECUTE 権限が必要です。

PostgreSQL では、コード手順または関数を作成するには、ユーザーには USAGE 権限が必要です。プロシージャまたは関数を実行するには、ユーザーがプロシージャまたは関数に対する EXECUTE 権限を持っている必要があります。

デフォルトでは、PL/pgSQL のプロシージャまたは関数は SECURITY INVOKER として定義されます。つまり、プロシージャまたは関数は、呼び出し元となるユーザーの権限で実行されます。または、SECURITY DEFINER を指定すると、関数を所有するユーザーの権限で関数を実行できます。

Cloud SQL for PostgreSQL のストアド プロシージャと関数の構文

次の例は、Cloud SQL for PostgreSQL のストアド プロシージャ関数の構文を示しています。

CREATE [ OR REPLACE ] PROCEDURE
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
  } ...

CREATE [ OR REPLACE ] FUNCTION
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
    [ RETURNS rettype
      | RETURNS TABLE ( column_name column_type [, ...] ) ]
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | WINDOW
    | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
    | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | PARALLEL { UNSAFE | RESTRICTED | SAFE }
    | COST execution_cost
    | ROWS result_rows
    | SUPPORT support_function
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
  } ...

トリガー

トリガーは、特定のイベントが発生したときに実行されるストアド プロシージャです。Oracle では、トリガー イベントはテーブル、ビュー、スキーマ、またはデータベースに関連付けられます。トリガーとなるイベントの種類は次のとおりです。

  • データ操作言語(DML)ステートメント(例: INSERTUPDATEDELETE
  • データ定義言語(DDL)ステートメント(例: CREATEALTERDROP
  • データベース イベント(例: LOGONSTARTUPSHUTDOWN

Oracle のトリガーには次のタイプがあります。

  • シンプル トリガー: 指定したトリガー イベントの前後に 1 回だけ起動
  • 複合トリガー: 複数のイベントで起動
  • INSTEAD OF トリガー: 複雑な編集不可能なビューに対して透過的な更新メカニズムを提供する、特殊なタイプの DML トリガー
  • システム トリガー: 特定のデータベース イベントで起動

Cloud SQL for PostgreSQL では、特定のテーブル、ビュー、外部テーブルに対する DML オペレーションの前または後にトリガーが起動します。INSTEAD OF トリガーは、ビューの更新メカニズムを提供するためにサポートされています。DDL オペレーションのトリガーは、イベント トリガーと呼ばれます。Cloud SQL for PostgreSQL は、データベース イベントに基づく Oracle のシステム トリガーをサポートしていません。

Oracle のトリガーとは異なり、Cloud SQL for PostgreSQL のトリガーは、トリガーの本文として匿名の PL/pgSQL ブロックをサポートしていません。0 個以上の引数を取り、トリガータイプを返す名前付き関数は、トリガー宣言で指定する必要があります。この関数は、トリガーが起動すると実行されます。

Cloud SQL for PostgreSQL のトリガーとイベント トリガーの構文

次の例は、Cloud SQL for PostgreSQL のトリガーイベント トリガーの構文を示しています。

CREATE [ CONSTRAINT ] TRIGGER name { BEFORE | AFTER | INSTEAD OF } { event [ OR ... ] }
    ON table_name
    [ FROM referenced_table_name ]
    [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]
    [ REFERENCING { { OLD | NEW } TABLE [ AS ] transition_relation_name } [ ... ] ]
    [ FOR [ EACH ] { ROW | STATEMENT } ]
    [ WHEN ( condition ) ]
    EXECUTE { FUNCTION | PROCEDURE } function_name ( arguments )

event には、INSERTUPDATE [ OF column_name [, ... ] ]DELETETRUNCATE のいずれか 1 つを設定できます。

CREATE EVENT TRIGGER name
    ON event
    [ WHEN filter_value IN (filter_value [, ... ]) [ AND ... ] ]
    EXECUTE { FUNCTION | PROCEDURE } function_name()

event には、ddl_command_startddl_command_endtable_rewritesql_drop のいずれか 1 つを設定できます。

filter_value には TAG のみを設定できます。

filter_value は、サポートされているコマンドタグのいずれかに設定できます。

次のステップ