

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

# 將虛擬產生的資料欄從 Oracle 遷移至 PostgreSQL
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql"></a>

*Veeranjaneyulu Grandhi、Rajesh Madiwale 和 Ramesh Pathuri，Amazon Web Services*

## 總結
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql-summary"></a>

在 11 版和更早版本中，PostgreSQL 不提供直接等同於 Oracle 虛擬資料欄的功能。在從 Oracle 資料庫遷移至 PostgreSQL 第 11 版或更早版本時，處理虛擬產生的資料欄很困難，原因有兩個： 
+ 遷移期間看不到虛擬資料欄。
+ PostgreSQL 不支援版本 12 之前的`generate`表達式。

不過，有模擬類似功能的解決方法。當您使用 AWS Database Migration Service (AWS DMS) 將資料從 Oracle Database 遷移至 PostgreSQL 第 11 版及更早版本時，您可以使用觸發函數在虛擬產生的資料欄中填入值。此模式提供 Oracle 資料庫和 PostgreSQL 程式碼的範例，您可以用於此目的。在 AWS 上，您可以將 Amazon Relational Database Service (Amazon RDS) 用於 PostgreSQL，或將 Amazon Aurora PostgreSQL 相容版本用於 PostgreSQL 資料庫。

從 PostgreSQL 第 12 版開始，支援產生的資料欄。產生的資料欄可以即時從其他資料欄值計算，也可以計算和儲存。[PostgreSQL 產生的資料欄](https://www.postgresql.org/docs/12/ddl-generated-columns.html)類似於 Oracle 虛擬資料欄。

## 先決條件和限制
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql-prereqs"></a>

**先決條件**
+ 作用中的 AWS 帳戶
+ 來源 Oracle 資料庫 
+ Target PostgreSQL 資料庫 (Amazon RDS for PostgreSQL 或 Aurora PostgreSQL 相容）
+ [PL/pgSQL](https://www.postgresql.org/docs/current/plpgsql.html) 編碼專業知識

**限制**
+ 僅適用於第 12 版之前的 PostgreSQL 版本。 
+ 適用於 Oracle 資料庫 11g 版或更新版本。
+ 資料遷移工具不支援虛擬資料欄。
+ 僅適用於相同資料表中定義的資料欄。
+ 如果虛擬產生的資料欄是指確定性的使用者定義函數，則不能用作分割索引鍵資料欄。
+ 表達式的輸出必須是純量值。它無法傳回 Oracle 提供的資料類型、使用者定義的類型`LOB`、 或 `LONG RAW`。
+ 針對虛擬資料欄定義的索引等同於 PostgreSQL 中的函數型索引。
+ 必須收集資料表統計資料。

## 工具
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql-tools"></a>
+ [pgAdmin 4](https://www.pgadmin.org/) 是 PostgreSQL 的開放原始碼管理工具。此工具提供圖形界面，可簡化資料庫物件的建立、維護和使用。
+ [Oracle SQL Developer](https://www.oracle.com/database/sqldeveloper/) 是免費的整合開發環境，可在傳統和雲端部署中使用 Oracle 資料庫中的 SQL。 

## 史詩
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql-epics"></a>

### 建立來源和目標資料庫資料表
<a name="create-source-and-target-database-tables"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立來源 Oracle 資料庫資料表。 | 在 Oracle Database 中，使用下列陳述式建立具有虛擬產生資料欄的資料表。<pre>CREATE TABLE test.generated_column<br />( CODE NUMBER,<br />STATUS VARCHAR2(12) DEFAULT 'PreOpen',<br />FLAG CHAR(1) GENERATED ALWAYS AS (CASE UPPER(STATUS) WHEN 'OPEN' THEN 'N' ELSE 'Y' END) VIRTUAL VISIBLE<br />);</pre>在此來源資料表中，資料`STATUS`欄中的資料會透過 AWS DMS 遷移至目標資料庫。不過，資料`FLAG`欄會使用 `generate by`功能填入，因此 AWS DMS 在遷移期間看不到此資料欄。若要實作 的功能`generated by`，您必須使用目標資料庫中的觸發條件和函數來填入資料`FLAG`欄中的值，如下圖所示。 | DBA，應用程式開發人員 | 
| 在 AWS 上建立目標 PostgreSQL 資料表。 | 使用下列陳述式在 AWS 上建立 PostgreSQL 資料表。<pre>CREATE TABLE test.generated_column<br />(<br />    code integer not null,<br />    status character varying(12) not null ,<br />    flag character(1)<br />);</pre>在此資料表中，資料`status`欄是標準資料欄。`flag` 資料欄將根據資料欄中的資料產生資料`status`欄。 | DBA，應用程式開發人員 | 

### 建立觸發函數來處理 PostgreSQL 中的虛擬資料欄
<a name="create-a-trigger-function-to-handle-the-virtual-column-in-postgresql"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立 PostgreSQL 觸發。 | 在 PostgreSQL 中，建立觸發條件。<pre>CREATE TRIGGER tgr_gen_column<br />AFTER INSERT OR UPDATE OF status ON test.generated_column<br />FOR EACH ROW <br />EXECUTE FUNCTION test.tgf_gen_column();</pre> | DBA，應用程式開發人員 | 
| 建立 PostgreSQL 觸發函數。 | 在 PostgreSQL 中，為觸發建立 函數。此函數會填入由應用程式或 AWS DMS 插入或更新的虛擬資料欄，並驗證資料。<pre>CREATE OR REPLACE FUNCTION test.tgf_gen_column() RETURNS trigger AS $VIRTUAL_COL$<br />BEGIN<br />IF (TG_OP = 'INSERT') THEN<br />IF (NEW.flag IS NOT NULL) THEN<br />RAISE EXCEPTION 'ERROR: cannot insert into column "flag"' USING DETAIL = 'Column "flag" is a generated column.';<br />END IF;<br />END IF;<br />IF (TG_OP = 'UPDATE') THEN<br />IF (NEW.flag::VARCHAR != OLD.flag::varchar) THEN<br />RAISE EXCEPTION 'ERROR: cannot update column "flag"' USING DETAIL = 'Column "flag" is a generated column.';<br />END IF;<br />END IF;<br />IF TG_OP IN ('INSERT','UPDATE') THEN<br />IF (old.flag is NULL) OR (coalesce(old.status,'') != coalesce(new.status,'')) THEN<br />UPDATE test.generated_column<br />SET flag = (CASE UPPER(status) WHEN 'OPEN' THEN 'N' ELSE 'Y' END)<br />WHERE code = new.code;<br />END IF;<br />END IF;<br />RETURN NEW;<br />END<br />$VIRTUAL_COL$ LANGUAGE plpgsql;</pre> | DBA，應用程式開發人員 | 

### 使用 AWS DMS 測試資料遷移
<a name="test-data-migration-by-using-aws-dms"></a>


| 任務 | Description | 所需的技能 | 
| --- | --- | --- | 
| 建立複寫執行個體。 | 若要建立複寫執行個體，請遵循 AWS DMS 文件中[的指示](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_ReplicationInstance.Creating.html)。複寫執行個體應與來源和目標資料庫位於相同的虛擬私有雲端 (VPC) 中。 | DBA，應用程式開發人員 | 
| 建立來源和目標端點。 | 若要建立端點，請遵循 AWS DMS 文件中[的指示](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Endpoints.Creating.html)。 | DBA，應用程式開發人員 | 
| 測試端點連線。 | 您可以透過指定 VPC 和複寫執行個體，然後選擇**執行**測試來測試端點連線。 | DBA，應用程式開發人員 | 
| 建立並啟動完整載入任務。 | 如需說明，請參閱 AWS DMS 文件中的[建立任務](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.Creating.html)和[完全載入任務設定](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.CustomizingTasks.TaskSettings.FullLoad.html)。 | DBA，應用程式開發人員 | 
| 驗證虛擬資料欄的資料。 | 比較來源和目標資料庫中虛擬資料欄中的資料。您可以手動驗證資料或撰寫此步驟的指令碼。 | DBA，應用程式開發人員 | 

## 相關資源
<a name="migrate-virtual-generated-columns-from-oracle-to-postgresql-resources"></a>
+ [AWS Database Migration Service 入門](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_GettingStarted.html) (AWS DMS 文件）
+ [使用 Oracle 資料庫做為 AWS DMS 的來源](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.Oracle.html) (AWS DMS 文件）
+ [使用 PostgreSQL 資料庫做為 AWS DMS 的目標 ](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.PostgreSQL.html)(AWS DMS 文件）
+ [PostgreSQL 中產生的資料欄](https://www.postgresql.org/docs/12/ddl-generated-columns.html) (PostgreSQL 文件）
+ [觸發函數](https://www.postgresql.org/docs/12/plpgsql-trigger.html) (PostgreSQL 文件）
+ Oracle 資料庫中的[虛擬資料欄](https://docs.oracle.com/database/121/SQLRF/statements_7002.htm#SQLRF01402) (Oracle 文件）