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

- Name
- Harry Chang
當企業決定導入 AI Agent 來協助老闆或業務主管分析營運狀況時,最常犯的錯誤就是「直接把 AI 接到核心 ERP 資料庫(如 Oracle)上」。
這不僅會因為 AI 產生錯誤的 SQL 語法拖垮營運系統效能,更可怕的是,客戶的真實姓名、電話與底價等商業機密,可能會被 AI 當作回答的素材直接洩漏出去。
因此,在我們這 12 天的「鞋墊廠訂單戰情 Agent」實戰專案中,我們的第一步,也是最關鍵的一步:建立一條安全的 ETL(萃取、轉換、載入)管線,將資料去識別化後,存入獨立的 PostgreSQL 庫中。
為什麼要特地把資料搬到 PostgreSQL?
在我們的鞋墊廠場景中,我們希望 AI 能分析「各廠區、各品牌、每個月的訂單與出貨狀況」。為了兼顧效能與資安,我們將整個數據管線的架構設計如下:
這樣做有兩大好處:
- 物理隔離:PostgreSQL 是一個完全獨立的資料庫,就算 AI Agent 發瘋下達了
DROP TABLE,受傷的也只是中介庫,Oracle ERP 依舊安然無恙。 - 乾淨的知識邊界:在寫入 PostgreSQL 前,我們已經把所有敏感欄位(如真實客戶名稱)轉換成代號。Agent 從根本上就「看不見」機密,自然就沒有洩密的風險。
鞋墊廠訂單資料:去識別化 Sample
以下是我們從 Oracle 撈出,並經過 Python 腳本「去識別化」後,準備存入 PostgreSQL 的 10 筆樣本資料。
這份資料涵蓋了鞋墊廠最核心的營運維度:生產廠區 (Factory)、品牌 (Brand)、鞋墊類型 (Type) 以及單價與金額。
| order_id | order_date | factory_code | brand_name | insole_type | customer_id | order_qty | unit_price | total_amount | shipped_qty |
|---|---|---|---|---|---|---|---|---|---|
| ORD-1001 | 2024-01-15 | TW-01 (台灣) | Nike | PU 發泡鞋墊 | CUST_A01 | 50,000 | 1.2 | 60,000 | 50,000 |
| ORD-1002 | 2024-01-18 | VN-02 (越南) | Adidas | EVA 成型鞋墊 | CUST_B02 | 120,000 | 0.8 | 96,000 | 120,000 |
| ORD-1003 | 2024-02-05 | VN-02 (越南) | New Balance | PU 發泡鞋墊 | CUST_C03 | 85,000 | 1.1 | 93,500 | 40,000 |
| ORD-1004 | 2024-02-12 | TW-01 (台灣) | Puma | EVA 成型鞋墊 | CUST_D04 | 30,000 | 0.9 | 27,000 | 30,000 |
| ORD-1005 | 2024-03-01 | ID-03 (印尼) | Asics | PU 發泡鞋墊 | CUST_E05 | 200,000 | 1.15 | 230,000 | 0 |
| ORD-1006 | 2024-03-15 | VN-02 (越南) | Nike | EVA 成型鞋墊 | CUST_A01 | 15,000 | 0.85 | 12,750 | 15,000 |
| ORD-1007 | 2024-04-02 | TW-01 (台灣) | Adidas | PU 發泡鞋墊 | CUST_B02 | 60,000 | 1.25 | 75,000 | 20,000 |
| ORD-1008 | 2024-04-20 | ID-03 (印尼) | Under Armour | EVA 成型鞋墊 | CUST_F06 | 110,000 | 0.95 | 104,500 | 110,000 |
| ORD-1009 | 2024-05-10 | VN-02 (越南) | New Balance | PU 發泡鞋墊 | CUST_C03 | 90,000 | 1.1 | 99,000 | 0 |
| ORD-1010 | 2024-05-22 | TW-01 (台灣) | Asics | EVA 成型鞋墊 | CUST_E05 | 45,000 | 0.9 | 40,500 | 45,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 階段將 VN、Vietnam、越廠 等字眼統一為 VN-02,這能大幅降低未來 Agent 在查詢時的混淆。
步驟 3:建立排程機制
不要手動匯出 CSV。一開始就可以寫好簡單的 Python 腳本,設定 Windows Task Scheduler 或 Linux Cron,讓 PostgreSQL 的資料每天清晨自動與 Oracle 保持同步(T+1 日資料更新)。
我的反思
在這個「萬物皆可 AI」的時代,許多開發者急於把最新、最酷的模型套用到公司的資料上,卻忽略了資料工程中最樸實無華的 ETL 與資安防護。
這就好像蓋房子,AI Agent 是裝潢精美的大廳,但「去識別化」與「中介資料庫」才是深埋在地下的地基。如果地基不穩,大廳蓋得再漂亮,一旦發生資料外洩,整個專案就會瞬間崩塌。
今天我們把乾淨的鞋墊廠訂單存進了 PostgreSQL。接下來,我們將在這座中介庫之上,架設一層安全的 API,為 AI Agent 的到來鋪好最後一哩路!