一、Oracle环境准备

1. Windows虚拟机

2. Docker

sudo docker run -d --name oracle-test1 \ -p 1521:1521 -p 5500:5500 \ -e ORACLE_PWD=$PASSWD, \ container-registry.oracle.com/database/express:latest
# 2025-0410 最新版docker为oracle21c
 
# 连接到oracle数据库有两种方式
# 1. 安装客户端后使用sqlplus
# sqlplus system/($PASSWD),@localhost:1521/XE
# 2. 进docker bash环境 默认oracle用户为system,服务名XE,密码为命令行参数设置的。
sudo docker exec -it oracle-test1 bash sqlplus system/($PASSWD)@XE

二、插件编译环境准备

1. Oracle客户端环境

https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html 
# 根据要连接的oracle版本选择客户端版本,我这里使用的oracle版本是21c 
mkdir -d /opt/oraClient 
unzip -d /opt/oraClient instantclient-basic-linux.x64* 
unzip -d /opt/oraClient instantclient-sdk-linux.x64* 
unzip -d /opt/oraClient instantclient-sqlplus-linux.x64* 
#确保存在libclntsh.so和libocci.so的软链接,不然编译oracle_fdw找不到 
# cd /opt/oraClient/instantclient* 
# ln -s libclntsh.so.12.1 libclntsh.so 
# ln -s libocci.so.12.1 libocci.so 
 
#客户端的so加到LD_LIBRARY_PATH
cd /etc/ld.so.conf.d/ vi oracle-x86_64.conf 
################################## 
/opt/oraClient/instantclient_21_17 
################################## 
sudo ldconfig

2. pg环境

# 将插件的使用环境版本的pg路径加到环境变量中
export DB14_17_HOME=/usr/local/postgres/14.17
export PGPORT=5866
export PATH=$DB14_17_HOME/bin:$PATH
export PGDATA=$HOME/data

注意部分版本不兼容:

Due to API breaks in PostgreSQL minor releases, the following PostgreSQL versions cannot be used:

  • 9.6.0 to 9.6.8
  • 10.0 to 10.3
  • 11.0 to 11.10
  • 12.0 to 12.5
  • 13.0 to 13.9
  • 14.0 to 14.6
  • 15.0 to 15.1

三、编译

export ORACLE_HOME=/opt/oraClient/instantclient_21_17 make PG_CONFIG=$DB14_17_HOME/bin/pg_config sudo make PG_CONFIG=$DB14_17_HOME/bin/pg_config install

可能遇到的问题,通常与pg版本不兼容,找不到客户端依赖头文件,依赖库有关

# pg版本不兼容
[postgres@localhost oracle_fdw-ORACLE_FDW_2_7_0]$ make gcc -std=gnu99 -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fPIC -I"/sdk/include" -I"/oci/include" -I"/rdbms/public" -I"/"  -I. -I./ -I/home/highgo/HighGo4.5.6-see/include/postgresql/server -I/home/highgo/HighGo4.5.6-see/include/postgresql/internal  -D_GNU_SOURCE -I/usr/include/libxml2   -c -o oracle_fdw.o oracle_fdw.c 
oracle_fdw.c: In function ‘oracleBeginForeignInsert’: 
oracle_fdw.c:1942:25: error: ‘ResultRelInfo’ has no member named ‘ri_RootResultRelInfo’    resultRelation = rinfo->ri_RootResultRelInfo->ri_RangeTableIndex;
^ 
make: *** [oracle_fdw.o] Error 1 
[postgres@localhost oracle_fdw-ORACLE_FDW_2_7_0]$ vi ~/.bash_profile  [postgres@localhost oracle_fdw-ORACLE_FDW_2_7_0]$ pg_config --version 
PostgreSQL 12.1 
[postgres@localhost oracle_fdw-ORACLE_FDW_2_7_0]$ postgres --version 
postgres (PostgreSQL) 12.1 
[postgres@localhost oracle_fdw-ORACLE_FDW_2_7_0]$ which postgres /home/highgo/HighGo4.5.6-see/bin/postgres

四、创建插件,使用

这里设计的使用流程为:

  1. pg创建外部服务器和oracle用户映射,创建pg中对应oracle中表的外部表
  2. pg中查询oracle中的表
  3. pg向oracle中插入数据
  4. oracle中查询是否插入成功
-- oracle表 employees CREATE TABLE employees ( 
id NUMBER PRIMARY KEY, 
name VARCHAR2(50), 
salary NUMBER ); 
-- pg插入后,oracle查询 
SELECT * FROM EMPLOYEES; 
ID NAME SALARY 
---------- -------------------- ---------- 
1 John Doe 50000
-- postgres
create extension oracle_fdw;
-- 创建外部服务器
CREATE SERVER oracle_test_server
FOREIGN DATA WRAPPER oracle_fdw
OPTIONS (
dbserver '//localhost:1521/XE'
);
 
-- 创建用户映射,pg用户映射到oracle用户
CREATE USER MAPPING FOR CURRENT_USER
SERVER oracle_test_server
OPTIONS (
	user 'system', 
	password '1qazWSX,' 
);
 
-- 创建外部表
CREATE FOREIGN TABLE foreign_employees ( 
	id INTEGER, 
	name VARCHAR(50), 
	salary NUMERIC 
)
SERVER oracle_test_server
OPTIONS ( 
	schema 'SYSTEM', -- Oracle 用户的 schema(默认是用户名大写)
	table 'EMPLOYEES' -- Oracle 表名(需大写) 
);
 
-- 查询外部表 
SELECT * FROM foreign_employees; 
 
-- 插入测试数据(如果 Oracle 用户有写权限) 
INSERT INTO foreign_employees (id, name, salary) 
VALUES (1, 'John Doe', 50000);