

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 使用 oracle\$1fdw 擴充功能處理 Oracle 資料庫
<a name="postgresql-oracle-fdw"></a>

若要從您的 RDS for PostgreSQL 資料庫執行個體 存取 Oracle 資料庫，您可以安裝並使用 `oracle_fdw` 擴充功能。此擴充功能是 Oracle 資料庫的外部資料包裝函式。若要進一步了解此擴充功能，請參閱 [oracle\$1fdw](https://github.com/laurenz/oracle_fdw) 文件。

RDS for PostgreSQL 12.7、13.3 版及更高版本支援此 `oracle_fdw` 擴充功能。

**Topics**
+ [開啟 oracle\$1fdw 擴充功能](#postgresql-oracle-fdw.enabling)
+ [範例：使用 Amazon RDS for Oracle Database 的外部伺服器連結](#postgresql-oracle-fdw.example)
+ [在傳輸中使用加密](#postgresql-oracle-fdw.encryption)
+ [了解 pg\$1user\$1mappings 檢視和許可權限](#postgresql-oracle-fdw.permissions)

## 開啟 oracle\$1fdw 擴充功能
<a name="postgresql-oracle-fdw.enabling"></a>

如要使用 oracle\$1fdw 擴充功能，請執行下列程序。

**如要開啟 oracle\$1fdw 擴充功能**
+ 使用具有 `rds_superuser` 許可的帳戶執行下列命令。

  ```
  CREATE EXTENSION oracle_fdw;
  ```

## 範例：使用 Amazon RDS for Oracle Database 的外部伺服器連結
<a name="postgresql-oracle-fdw.example"></a>

下列範例顯示使用連結至 Amazon RDS for Oracle 資料庫的外部伺服器。

**若要建立連結至 RDS for Oracle 資料庫的外部伺服器**

1. 請注意以下 RDS for Oracle 資料庫執行個體的事項：
   + 端點
   + 連線埠
   + 資料庫名稱

1. 建立外部伺服器。

   ```
   test=> CREATE SERVER oradb FOREIGN DATA WRAPPER oracle_fdw OPTIONS (dbserver '//endpoint:port/DB_name');
   CREATE SERVER
   ```

1. 授予使用權限給沒有 `rds_superuser` 權限的使用者，例如 `user1`。

   ```
   test=> GRANT USAGE ON FOREIGN SERVER oradb TO user1;
   GRANT
   ```

1. 連線為 `user1` 並建立一個對應至 Oracle 使用者的映射。

   ```
   test=> CREATE USER MAPPING FOR user1 SERVER oradb OPTIONS (user 'oracleuser', password 'mypassword');
   CREATE USER MAPPING
   ```

1. 建立連結至 Oracle 資料表的外部資料表。

   ```
   test=> CREATE FOREIGN TABLE mytab (a int) SERVER oradb OPTIONS (table 'MYTABLE');
   CREATE FOREIGN TABLE
   ```

1. 查詢外部資料表。

   ```
   test=>  SELECT * FROM mytab;
   a
   ---
   1
   (1 row)
   ```

如果查詢報告下列錯誤，請檢查您的安全群組和存取控制清單 (ACL)，以確定這兩個執行個體可以通訊。

```
ERROR: connection for foreign table "mytab" cannot be established
DETAIL: ORA-12170: TNS:Connect timeout occurred
```

## 在傳輸中使用加密
<a name="postgresql-oracle-fdw.encryption"></a>

傳輸中的 PostgreSQL-to-Oracle 加密是以從用戶端和伺服器組態參數的組合為依據。如需使用 Oracle 21c 的範例，請參閱 Oracle 文件中的[關於溝通加密和完整性的值](https://docs.oracle.com/en/database/oracle/oracle-database/21/dbseg/configuring-network-data-encryption-and-integrity.html#GUID-3A2AF4AA-AE3E-446B-8F64-31C48F27A2B5)。在 Amazon RDS 上用於 oracle\$1fdw 的用戶端已設定為 `ACCEPTED`，表示加密取決於 Oracle 資料庫伺服器組態，其會使用 Oracle 安全性程式庫 (libnnz) 進行加密。

如果資料庫位於 RDS for Oracle，請參閱 [Oracle 原生網路加密](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.Oracle.Options.NetworkEncryption.html)以設定加密。

## 了解 pg\$1user\$1mappings 檢視和許可權限
<a name="postgresql-oracle-fdw.permissions"></a>

PostgreSQL 目錄 `pg_user_mapping` 儲存從 RDS-PostgreSQL 使用者新增至外部資料 (遠端) 伺服器上使用者的映射。存取目錄受到限制，但您使用 `pg_user_mappings` 檢視查看映射。接下來，您可找到一個範例，其顯示許可權限如何套用於範例 Oracle 資料庫，但此資訊通常適用於任何外部資料包裝函式。

在以下輸出中，您可以找到映射至三個不同範例使用者的角色和權限。使用者 `rdssu1` 和 `rdssu2` 是 `rds_superuser` 角色的成員，`user1` 則不是。此範例使用 `psql` 中繼命令 `\du` 來列出現有角色。

```
test=>  \du
                                                               List of roles
    Role name    |                         Attributes                         |                          Member of
-----------------+------------------------------------------------------------+-------------------------------------------------------------
 rdssu1          |                                                            | {rds_superuser}
 rdssu2          |                                                            | {rds_superuser}
 user1           |                                                            | {}
```

所有使用者，包括具有 `rds_superuser` 權限的使用者，可在 `pg_user_mappings` 資料表中查看自己的使用者映射 (`umoptions`)。如以下範例所示，當 `rdssu1` 嘗試獲取所有使用者映射，即使有 `rdssu1``rds_superuser` 權限，仍會引起錯誤：

```
test=> SELECT * FROM pg_user_mapping;
ERROR: permission denied for table pg_user_mapping
```

下列是一些範例。

```
test=> SET SESSION AUTHORIZATION rdssu1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     | {user=oracleuser,password=mypwd}
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)

test=> SET SESSION AUTHORIZATION rdssu2;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |            umoptions
-------+-------+---------+--------+------------+----------------------------------
 16414 | 16411 | oradb   |  16412 | user1      |
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     | {user=oracleuser,password=mypwd}
 (3 rows)

test=> SET SESSION AUTHORIZATION user1;
SET
test=> SELECT * FROM pg_user_mappings;
 umid  | srvid | srvname | umuser | usename    |           umoptions
-------+-------+---------+--------+------------+--------------------------------
 16414 | 16411 | oradb   |  16412 | user1      | {user=oracleuser,password=mypwd}
 16423 | 16411 | oradb   |  16421 | rdssu1     |
 16424 | 16411 | oradb   |  16422 | rdssu2     |
 (3 rows)
```

由於實作 `information_schema._pg_user_mappings` 和 `pg_catalog.pg_user_mappings` 存在差異，手動建立的 `rds_superuser` 需要額外的許可才能在 `pg_catalog.pg_user_mappings` 上檢視密碼。

`rds_superuser` 不需要額外許可才能在 `information_schema._pg_user_mappings` 中檢視密碼。

沒有 `rds_superuser` 角色的使用者僅能在以下情況下在 `pg_user_mappings` 中檢視密碼：
+ 目前使用者是被映射的使用者，且擁有伺服器或擁有伺服器上 `USAGE` 的權限。
+ 目前使用者是伺服器擁有者，且映射適用於 `PUBLIC`。