0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

oracle_fdwでOracleの日本語カラム名を英語カラムにマッピングしてみた

0
Posted at

背景

以前、Aurora PostgreSQLからFDWでOracle on EC2に接続してMviewの動作を確認をしました。
今回は、FDWの外部テーブルの動作をさらに深掘りし、以下を検証します。

  • Oracle(JA16SJIS)の日本語カラム名テーブルを、Aurora PostgreSQL(UTF-8)の外部テーブルで英語カラム名にマッピングできるか
  • Mviewリフレッシュが問題なく動作するか

まとめ

  • oracle_fdwのtableオプションにサブクエリを指定することで、Oracleの日本語カラム名をAurora PostgreSQLの外部テーブルで英語カラム名にマッピングできた
  • サブクエリ方式ではschemaオプションとの併用ができないため、サブクエリ内でスキーマを指定する必要がある
  • Mviewリフレッシュ(CONCURRENTLY含む)も問題なく動作した

実装

今回、下記の環境でテストします

image.png

Sqlplusをインストール

1.こちらにアクセスして下記をダウンロードします

  • instantclient-basic-macos.x64-19.16.0.0.0dbru.dmg
  • instantclient-sqlplus-macos.x64-19.16.0.0.0dbru.dmg

image.png

2.basicをインストールします

/Volumes/instantclient-basic-macos.x64-19.16.0.0.0dbru/install_ic.sh

3.sqlplusをインストールします

 /Volumes/instantclient-sqlplus-macos.x64-19.16.0.0.0dbru/install_ic.sh

4.フォルダを移動します

sudo mv /Users/XXXX/Downloads/instantclient_19_16 /usr/local/oracle/

Oracleのセットアップ

インフラ

以前、構築したEC2を使用します。

ユーザ(スキーマ)の作成

  1. testユーザとfdwuserを作成します
SQL> CREATE USER test IDENTIFIED BY XXXX DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS;
CREATE USER fdwuser IDENTIFIED BY XXXX DEFAULT TABLESPACE USERS QUOTA UNLIMITED ON USERS;
GRANT CONNECT TO test;
GRANT RESOURCE TO test;
GRANT CONNECT TO fdwuser;
User created.

SQL>
User created.

SQL>
Grant succeeded.

SQL>
Grant succeeded.

SQL>

Grant succeeded.

SQL>

テーブルの作成(testスキーマ)

2種類のテーブルを作成します。

  1. testユーザでOracleに接続します

英字カラムのテーブルを作成

1.employeeテーブルを作成します。

SQL> CREATE TABLE employees (
  id NUMBER PRIMARY KEY,
  name VARCHAR2(100),
  department VARCHAR2(50),
  created_date DATE DEFAULT SYSDATE
);  2    3    4    5    6

Table created.

SQL>

SQL> desc employees
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER
 NAME                                               VARCHAR2(100)
 DEPARTMENT                                         VARCHAR2(50)
 CREATED_DATE                                       DATE

SQL>

2.データを登録します

SQL> INSERT INTO employees VALUES (1, 'Tanaka Taro', 'Sales', SYSDATE);
INSERT INTO employees VALUES (2, 'Suzuki Hanako', 'Engineering', SYSDATE);
INSERT INTO employees VALUES (3, 'Sato Jiro', 'Marketing', SYSDATE);
COMMIT;
1 row created.

SQL>
1 row created.

SQL>
1 row created.

SQL>

Commit complete.

SQL>

3.データが登録されました

SQL> SELECT * FROM employees;

        ID NAME                                                                                                 DEPARTMENT                                         CREATED_DATE
---------- ---------------------------------------------------------------------------------------------------- -------------------------------------------------- -------------------
         1 Tanaka Taro                                                                                          Sales                                              2026/03/20 03:42:07
         2 Suzuki Hanako                                                                                        Engineering                                        2026/03/20 03:42:07
         3 Sato Jiro                                                                                            Marketing                                          2026/03/20 03:42:07

SQL>

日本語カラムテーブルの作成(testスキーマ)

1.PCでターミナルを開きます
2.ポートフォワードします

% aws ssm start-session \            
  --target i-XXXXXX \
  --document-name AWS-StartPortForwardingSession \
  --parameters '{"portNumber":["1521"],"localPortNumber":["1521"]}' \
  --region ap-northeast-1

Starting session with SessionId: XXXXXX
Port 1521 opened for sessionId XXXXXX.
Waiting for connections...

3.ターミナルの文字コードを日本語(Shift JIS)に変更します
image.png

4.もう一枚ターミナルを開きます
5.環境変数を設定します

export PATH=/usr/local/oracle:$PATH
export DYLD_LIBRARY_PATH=/usr/local/oracle
export NLS_LANG=JAPANESE_JAPAN.JA16SJIS

6.sqlplusで接続します

% sqlplus test/XXXXXX@//localhost:1521/ORCL

SQL*Plus: Release 19.0.0.0.0 - Production on  3 20 12:25:16 2026
Version 19.16.0.0.0

Copyright (c) 1982, 2020, Oracle.  All rights reserved.



Oracle Database 11g Release 11.2.0.1.0 - 64bit Production
に接続されました。
SQL> 

7.テーブルを作成します

CREATE TABLE employees_jp (
 "社員ID" NUMBER PRIMARY KEY,
 "氏名" VARCHAR2(100),
 "部署" VARCHAR2(50),
 "作成日" DATE DEFAULT SYSDATE
);

8.できました

SQL> DESC employees_jp;
 名前					   NULL?    
 ----------------------------------------- -------- ----------------------------
 社員ID 				   NOT NULL NUMBER
 氏名						    VARCHAR2(100)
 部署						    VARCHAR2(50)
 作成日 					    DATE

SQL> 

9.データを登録します

INSERT INTO employees_jp VALUES (101, '山田一郎', '総務部', SYSDATE);
INSERT INTO employees_jp VALUES (102, '高橋美月', '人事部', SYSDATE);
INSERT INTO employees_jp VALUES (103, '渡辺健太', '経理部', SYSDATE);
COMMIT;

10.登録されました

SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY/MM/DD HH24:MI:SS';

セッションが変更されました。

SQL> SELECT * FROM employees_jp;

    社員ID 氏名 												部署						   作成日
---------- ---------------------------------------------------------------------------------------------------- -------------------------------------------------- -------------------
       101 山田一郎												総務部						   2026/03/20 03:34:17
       102 高橋美月												人事部						   2026/03/20 03:34:17
       103 渡辺健太												経理部						   2026/03/20 03:34:17

SQL> 

fdwuserへの権限付与

1.作成したテーブルに権限を付与します

SQL> GRANT SELECT ON test.employees TO fdwuser;
GRANT SELECT ON test.employees_jp TO fdwuser;
Grant succeeded.

SQL>

Grant succeeded.

SQL>

2.付与されました

SQL> SELECT grantor, table_name, privilege FROM all_tab_privs WHERE grantee = 'FDWUSER';

GRANTOR                        TABLE_NAME                     PRIVILEGE
------------------------------ ------------------------------ ----------------------------------------
TEST                           EMPLOYEES                      SELECT
TEST                           EMPLOYEES_JP                   SELECT

SQL>

Auroraのセットアップ

  1. psqlでAuroraに接続します

oracle_fdw拡張を有効化

1.oracle_fdw拡張を有効化します

postgres=> CREATE EXTENSION oracle_fdw;
CREATE EXTENSION
postgres=>

2.外部サーバー作成(Oracle EC2に接続) をします

postgres=> CREATE SERVER oracle_ec2
postgres-> FOREIGN DATA WRAPPER oracle_fdw
postgres-> OPTIONS (dbserver '//EC2のIPアドレス:1521/ORCL');
CREATE SERVER
postgres=>

3.ユーザーマッピング(fdwuserで接続)を作成します

postgres=> CREATE USER MAPPING FOR postgres
postgres-> SERVER oracle_ec2
postgres-> OPTIONS (user 'fdwuser', password 'XXXXX');
CREATE USER MAPPING
postgres=>

外部テーブルの作成

英語カラムテーブル

1.外部テーブルを作成します

postgres=> CREATE FOREIGN TABLE fdw_employees (
postgres(>   id INTEGER,
postgres(>   name VARCHAR(100),
postgres(>   department VARCHAR(50),
postgres(>   created_date TIMESTAMP
postgres(> ) SERVER oracle_ec2
postgres-> OPTIONS (schema 'TEST', table 'EMPLOYEES');
CREATE FOREIGN TABLE
postgres=>

2.定義を確認します

postgres=> \d fdw_employees
                           Foreign table "public.fdw_employees"
    Column    |            Type             | Collation | Nullable | Default | FDW options
--------------+-----------------------------+-----------+----------+---------+-------------
 id           | integer                     |           |          |         |
 name         | character varying(100)      |           |          |         |
 department   | character varying(50)       |           |          |         |
 created_date | timestamp without time zone |           |          |         |
Server: oracle_ec2
FDW options: (schema 'TEST', "table" 'EMPLOYEES')

postgres=>

3.見えました

postgres=> select * from fdw_employees;
 id |     name      | department  |    created_date
----+---------------+-------------+---------------------
  1 | Tanaka Taro   | Sales       | 2026-03-20 03:42:07
  2 | Suzuki Hanako | Engineering | 2026-03-20 03:42:07
  3 | Sato Jiro     | Marketing   | 2026-03-20 03:42:07
(3 rows)

postgres=>

日本語カラム→英語カラム名にマッピング

日本語カラムを英語カラムにマッピングするには、tableオプション句でサブクエリのASを使ってカラムを定義します

1.外部テーブルを作成します

postgres=> CREATE FOREIGN TABLE fdw_employees_jp (
postgres(>   employee_id INTEGER,
postgres(>   name VARCHAR(100),
postgres(>   department VARCHAR(50),
postgres(>   created_date TIMESTAMP
postgres(> ) SERVER oracle_ec2
postgres-> OPTIONS (table '(SELECT "社員ID" AS employee_id, "氏名" AS name, "部署" AS department, "作成日" AS created_date FROM TEST.employees_jp)');
CREATE FOREIGN TABLE
postgres=>

2.定義を確認します

postgres=> \d fdw_employees_jp
                          Foreign table "public.fdw_employees_jp"
    Column    |            Type             | Collation | Nullable | Default | FDW options
--------------+-----------------------------+-----------+----------+---------+-------------
 employee_id  | integer                     |           |          |         |
 name         | character varying(100)      |           |          |         |
 department   | character varying(50)       |           |          |         |
 created_date | timestamp without time zone |           |          |         |
Server: oracle_ec2
FDW options: ("table" '(SELECT "社員ID" AS employee_id, "氏名" AS name, "部署" AS department, "作成日" AS created_date FROM TEST.employees_jp)')

postgres=>

3.データも見えました

postgres=> select * from fdw_employees_jp;
 employee_id |   name   | department |    created_date
-------------+----------+------------+---------------------
         101 | 山田一郎 | 総務部     | 2026-03-20 03:34:17
         102 | 高橋美月 | 人事部     | 2026-03-20 03:34:17
         103 | 渡辺健太 | 経理部     | 2026-03-20 03:34:17
(3 rows)

postgres=>


postgres=> select employee_id,name from fdw_employees_jp;
 employee_id |   name
-------------+----------
         101 | 山田一郎
         102 | 高橋美月
         103 | 渡辺健太
(3 rows)

postgres=>

Mviewの作成

英語テーブルのMview

1.Mviewを作成します

postgres=> CREATE MATERIALIZED VIEW mv_employees AS
postgres-> SELECT id, name, department, created_date FROM fdw_employees;
SELECT 3
postgres=>

postgres=> CREATE UNIQUE INDEX idx_mv_employees_id ON mv_employees(id);
CREATE INDEX
postgres=>

2.定義を確認します

postgres=> \d mv_employees
                   Materialized view "public.mv_employees"
    Column    |            Type             | Collation | Nullable | Default
--------------+-----------------------------+-----------+----------+---------
 id           | integer                     |           |          |
 name         | character varying(100)      |           |          |
 department   | character varying(50)       |           |          |
 created_date | timestamp without time zone |           |          |
Indexes:
    "idx_mv_employees_id" UNIQUE, btree (id)

postgres=>

postgres=> SELECT definition FROM pg_matviews WHERE matviewname = 'mv_employees';
           definition
--------------------------------
  SELECT fdw_employees.id,     +
     fdw_employees.name,       +
     fdw_employees.department, +
     fdw_employees.created_date+
    FROM fdw_employees;
(1 row)

postgres=>

3.データも見えました

postgres=> select * from mv_employees;
 id |     name      | department  |    created_date
----+---------------+-------------+---------------------
  1 | Tanaka Taro   | Sales       | 2026-03-20 03:42:07
  2 | Suzuki Hanako | Engineering | 2026-03-20 03:42:07
  3 | Sato Jiro     | Marketing   | 2026-03-20 03:42:07
(3 rows)

postgres=>

日本語テーブルのMview

1.Mviewを作成します

postgres=> CREATE MATERIALIZED VIEW mv_employees_jp AS
postgres-> SELECT employee_id, name, department, created_date FROM fdw_employees_jp;
SELECT 3
postgres=>


postgres=> CREATE UNIQUE INDEX idx_mv_employees_jp_id ON mv_employees_jp(employee_id);
CREATE INDEX
postgres=>

2.定義を確認します

postgres=> \d mv_employees_jp
                 Materialized view "public.mv_employees_jp"
    Column    |            Type             | Collation | Nullable | Default
--------------+-----------------------------+-----------+----------+---------
 employee_id  | integer                     |           |          |
 name         | character varying(100)      |           |          |
 department   | character varying(50)       |           |          |
 created_date | timestamp without time zone |           |          |
Indexes:
    "idx_mv_employees_jp_id" UNIQUE, btree (employee_id)

postgres=>


postgres=> SELECT definition FROM pg_matviews WHERE matviewname = 'mv_employees_jp';
              definition
---------------------------------------
  SELECT fdw_employees_jp.employee_id,+
     fdw_employees_jp.name,           +
     fdw_employees_jp.department,     +
     fdw_employees_jp.created_date    +
    FROM fdw_employees_jp;
(1 row)

postgres=>

3.データも見えました

postgres=> SELECT employee_id, name, department, created_date FROM fdw_employees_jp;
 employee_id |   name   | department |    created_date
-------------+----------+------------+---------------------
         101 | 山田一郎 | 総務部     | 2026-03-20 03:34:17
         102 | 高橋美月 | 人事部     | 2026-03-20 03:34:17
         103 | 渡辺健太 | 経理部     | 2026-03-20 03:34:17
(3 rows)

postgres=>

Mviewリフレッシュの確認

英語カラムのテーブル

データの登録(Oracle)

1.データを登録します

SQL> INSERT INTO employees VALUES (4, 'Yamada Ichiro', 'Finance', SYSDATE);
COMMIT;
1 row created.

SQL>

Commit complete.

2.データを確認します。登録されました

SQL> select * from employees;

        ID NAME                                                                                                 DEPARTMENT                                         CREATED_DATE
---------- ---------------------------------------------------------------------------------------------------- -------------------------------------------------- -------------------
         1 Tanaka Taro                                                                                          Sales                                              2026/03/20 03:42:07
         2 Suzuki Hanako                                                                                        Engineering                                        2026/03/20 03:42:07
         3 Sato Jiro                                                                                            Marketing                                          2026/03/20 03:42:07
         4 Yamada Ichiro                                                                                        Finance                                            2026/03/20 04:34:35

SQL>
データの確認(PostgreSQL 外部テーブル)

1.外部テーブルでデータが確認できました

postgres=> select * from fdw_employees;
 id |     name      | department  |    created_date
----+---------------+-------------+---------------------
  1 | Tanaka Taro   | Sales       | 2026-03-20 03:42:07
  2 | Suzuki Hanako | Engineering | 2026-03-20 03:42:07
  3 | Sato Jiro     | Marketing   | 2026-03-20 03:42:07
  4 | Yamada Ichiro | Finance     | 2026-03-20 04:34:35
(4 rows)

postgres=>
リフレッシュの確認(PostgreSQL Mview)

1.リフレッシュ前のデータを確認します。想定通り、Mview上でデータは見えません

postgres=> select * from mv_employees;
 id |     name      | department  |    created_date
----+---------------+-------------+---------------------
  1 | Tanaka Taro   | Sales       | 2026-03-20 03:42:07
  2 | Suzuki Hanako | Engineering | 2026-03-20 03:42:07
  3 | Sato Jiro     | Marketing   | 2026-03-20 03:42:07
(3 rows)

postgres=>

2.リフレッシュします

postgres=> REFRESH MATERIALIZED VIEW CONCURRENTLY mv_employees;
REFRESH MATERIALIZED VIEW
postgres=>

3.リフレッシュ後のデータを確認します。1行増えました

postgres=> select * from mv_employees;
 id |     name      | department  |    created_date
----+---------------+-------------+---------------------
  1 | Tanaka Taro   | Sales       | 2026-03-20 03:42:07
  2 | Suzuki Hanako | Engineering | 2026-03-20 03:42:07
  3 | Sato Jiro     | Marketing   | 2026-03-20 03:42:07
  4 | Yamada Ichiro | Finance     | 2026-03-20 04:34:35
(4 rows)

postgres=>

日本語カラムのテーブル

データの登録(Oracle)

1.データを登録します

INSERT INTO employees_jp VALUES (104, '中村美咲', '開発部', SYSDATE);
COMMIT;

2.データを確認します。登録されました

SQL> select * from employees_jp
  2  ;

    社員ID 氏名 												部署		   作成日
---------- ---------------------------------------------------------------------------------------------------- -------------------------------------------------- -------------------
       104 中村美咲												開発部		   2026/03/20 04:38:18
       101 山田一郎												総務部		   2026/03/20 03:34:17
       102 高橋美月												人事部		   2026/03/20 03:34:17
       103 渡辺健太												経理部		   2026/03/20 03:34:17

SQL> 
データの確認(PostgreSQL 外部テーブル)

1.外部テーブルでデータが確認できました

postgres=> select * from fdw_employees_jp;
 employee_id |   name   | department |    created_date
-------------+----------+------------+---------------------
         104 | 中村美咲 | 開発部     | 2026-03-20 04:38:18
         101 | 山田一郎 | 総務部     | 2026-03-20 03:34:17
         102 | 高橋美月 | 人事部     | 2026-03-20 03:34:17
         103 | 渡辺健太 | 経理部     | 2026-03-20 03:34:17
(4 rows)

postgres=>
リフレッシュの確認(PostgreSQL Mview)

1.リフレッシュ前のデータを確認します。想定通り、Mview上でデータは見えません

postgres=> select * from mv_employees_jp;
 employee_id |   name   | department |    created_date
-------------+----------+------------+---------------------
         101 | 山田一郎 | 総務部     | 2026-03-20 03:34:17
         102 | 高橋美月 | 人事部     | 2026-03-20 03:34:17
         103 | 渡辺健太 | 経理部     | 2026-03-20 03:34:17
(3 rows)

postgres=>

2.リフレッシュします

postgres=> REFRESH MATERIALIZED VIEW CONCURRENTLY mv_employees_jp;
REFRESH MATERIALIZED VIEW
postgres=>

3.リフレッシュ後のデータを確認します。1行増えました

postgres=> select * from mv_employees_jp;
 employee_id |   name   | department |    created_date
-------------+----------+------------+---------------------
         101 | 山田一郎 | 総務部     | 2026-03-20 03:34:17
         102 | 高橋美月 | 人事部     | 2026-03-20 03:34:17
         103 | 渡辺健太 | 経理部     | 2026-03-20 03:34:17
         104 | 中村美咲 | 開発部     | 2026-03-20 04:38:18
(4 rows)

postgres=>

考察

oracle_fdwのサブクエリ方式でカラム名をマッピングした。サブクエリ方式ではschemaオプションと併用できない点に注意が必要でした。
まだまだわかっていないことも多いので、機会があれば今後もoracle_fdwの検証を行いたいと思います。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?