【實戰】Day 18:從 Oracle 到 Postgres 的資料萃取與去識別化

【實戰】Day 18:從 Oracle 到 Postgres 的資料萃取與去識別化

開啟 12 天的企業訂單 Agent 實戰!第一步,我們探討如何安全地從 Oracle ERP 撈取鞋墊廠的原始訂單,進行客戶個資的去識別化,並轉存入 PostgreSQL 作為 AI 專屬的乾淨中介庫。


當企業決定導入 AI Agent 來協助老闆或業務主管分析營運狀況時,最常犯的錯誤就是「直接把 AI 接到核心 ERP 資料庫(如 Oracle)上」。

這不僅會因為 AI 產生錯誤的 SQL 語法拖垮營運系統效能,更可怕的是,客戶的真實姓名、電話與底價等商業機密,可能會被 AI 當作回答的素材直接洩漏出去。

因此,在我們這 12 天的「鞋墊廠訂單戰情 Agent」實戰專案中,我們的第一步,也是最關鍵的一步:建立一條安全的 ETL(萃取、轉換、載入)管線,將資料去識別化後,存入獨立的 PostgreSQL 庫中。


為什麼要特地把資料搬到 PostgreSQL?

在我們的鞋墊廠場景中,我們希望 AI 能分析「各廠區、各品牌、每個月的訂單與出貨狀況」。為了兼顧效能與資安,我們將整個數據管線的架構設計如下:

Loading Diagram...

這樣做有兩大好處:

  1. 物理隔離:PostgreSQL 是一個完全獨立的資料庫,就算 AI Agent 發瘋下達了 DROP TABLE,受傷的也只是中介庫,Oracle ERP 依舊安然無恙。
  2. 乾淨的知識邊界:在寫入 PostgreSQL 前,我們已經把所有敏感欄位(如真實客戶名稱)轉換成代號。Agent 從根本上就「看不見」機密,自然就沒有洩密的風險。

鞋墊廠訂單資料:去識別化 Sample

以下是我們從 Oracle 撈出,並經過 Python 腳本「去識別化」後,準備存入 PostgreSQL 的 10 筆樣本資料。

這份資料涵蓋了鞋墊廠最核心的營運維度:生產廠區 (Factory)品牌 (Brand)鞋墊類型 (Type) 以及單價與金額

order_idorder_datefactory_codebrand_nameinsole_typecustomer_idorder_qtyunit_pricetotal_amountshipped_qty
ORD-10012024-01-15TW-01 (台灣)NikePU 發泡鞋墊CUST_A0150,0001.260,00050,000
ORD-10022024-01-18VN-02 (越南)AdidasEVA 成型鞋墊CUST_B02120,0000.896,000120,000
ORD-10032024-02-05VN-02 (越南)New BalancePU 發泡鞋墊CUST_C0385,0001.193,50040,000
ORD-10042024-02-12TW-01 (台灣)PumaEVA 成型鞋墊CUST_D0430,0000.927,00030,000
ORD-10052024-03-01ID-03 (印尼)AsicsPU 發泡鞋墊CUST_E05200,0001.15230,0000
ORD-10062024-03-15VN-02 (越南)NikeEVA 成型鞋墊CUST_A0115,0000.8512,75015,000
ORD-10072024-04-02TW-01 (台灣)AdidasPU 發泡鞋墊CUST_B0260,0001.2575,00020,000
ORD-10082024-04-20ID-03 (印尼)Under ArmourEVA 成型鞋墊CUST_F06110,0000.95104,500110,000
ORD-10092024-05-10VN-02 (越南)New BalancePU 發泡鞋墊CUST_C0390,0001.199,0000
ORD-10102024-05-22TW-01 (台灣)AsicsEVA 成型鞋墊CUST_E0545,0000.940,50045,000

去識別化重點:原本 ERP 中的「客戶真實公司名稱」與「聯絡人電話」,在進入 PostgreSQL 時已全數替換為 CUST_A01 這種無意義的代碼。


程式碼概念解析:Python ETL 腳本

在實務上,我們會寫一支每天半夜固定執行的 Python 腳本(Cronjob)來做這件事。以下是核心概念的虛擬碼:

import pandas as pd
import cx_Oracle # Oracle 連線套件
from sqlalchemy import create_engine

# 1. 連接 Oracle ERP 並撈取原始訂單
oracle_conn = cx_Oracle.connect("user/password@erp_server")
raw_orders_df = pd.read_sql("SELECT * FROM erp_orders WHERE order_date >= '2023-01-01'", oracle_conn)

# 2. 進行去識別化 (Data Anonymization)
# 丟棄不需要的機密欄位(如客戶真實姓名、電話,以及絕對不能外流的「工廠成本價 cost_price」,保留「單價 unit_price」供後續分析)
raw_orders_df = raw_orders_df.drop(columns=['customer_real_name', 'contact_phone', 'cost_price'])

# 將客戶 ID 進行雜湊編碼 (Hashing) 或代碼對應
raw_orders_df['customer_id'] = raw_orders_df['customer_id'].apply(lambda x: generate_hash(x))

# 3. 存入供 AI 使用的 PostgreSQL 中介庫
pg_engine = create_engine('postgresql://ai_user:password@localhost:5432/ai_database')
raw_orders_df.to_sql('safe_orders', pg_engine, if_exists='replace', index=False)

透過這短短幾行程式,我們就完成了一道堅固的資安防火牆。


實用建議:三個起步行動

如果你也準備為公司打造類似的數據架構,請先執行以下三個步驟:

步驟 1:定義「AI 的視野範圍」

與業務主管討論,AI 究竟需要回答什麼問題?如果只需回答「出貨量」與「品牌佔比」,那就絕對不要把「產品毛利率」與「底價」撈進來。給的資料越少,風險越低。

步驟 2:統一各廠區的代碼 (Data Normalization)

在跨國製造業(如台灣廠、越南廠、印尼廠)中,各廠的 ERP 欄位名稱可能有異。在存入 PostgreSQL 前,務必在 Python 階段將 VNVietnam越廠 等字眼統一為 VN-02,這能大幅降低未來 Agent 在查詢時的混淆。

步驟 3:建立排程機制

不要手動匯出 CSV。一開始就可以寫好簡單的 Python 腳本,設定 Windows Task Scheduler 或 Linux Cron,讓 PostgreSQL 的資料每天清晨自動與 Oracle 保持同步(T+1 日資料更新)。


我的反思

在這個「萬物皆可 AI」的時代,許多開發者急於把最新、最酷的模型套用到公司的資料上,卻忽略了資料工程中最樸實無華的 ETL 與資安防護。

這就好像蓋房子,AI Agent 是裝潢精美的大廳,但「去識別化」與「中介資料庫」才是深埋在地下的地基。如果地基不穩,大廳蓋得再漂亮,一旦發生資料外洩,整個專案就會瞬間崩塌。

今天我們把乾淨的鞋墊廠訂單存進了 PostgreSQL。接下來,我們將在這座中介庫之上,架設一層安全的 API,為 AI Agent 的到來鋪好最後一哩路!