兩張表 TABLE_A、TABLE_B 無共同欄位,需 1:1 配對合併。常見做法:
-- 方法 1:ROWNUM 虛擬欄位
SELECT * FROM
(SELECT a.*, ROWNUM rn FROM table_a a) aa,
(SELECT b.*, ROWNUM rn FROM table_b b) bb
WHERE aa.rn = bb.rn;
ROWNUM 是**查詢結果集**的流水號,非儲存順序。ORDER BY 時,Oracle 以區塊讀取順序回傳,受平行度、快取、統計資訊影響極大。ROWNUM 配對結果**完全錯亂**(如 ID 1321 對到 1001321)。-- 步驟 1:建立序列
CREATE SEQUENCE merge_seq;
-- 步驟 2:為兩表各加 SEQ 欄位並更新
ALTER TABLE table_a ADD seq NUMBER;
UPDATE table_a SET seq = merge_seq.NEXTVAL; -- 耗時 ~5 分鐘/100萬筆
ALTER TABLE table_b ADD seq NUMBER;
UPDATE table_b SET seq = merge_seq.NEXTVAL; -- 需重置序列或用新序列
-- 步驟 3:以 SEQ 合併
SELECT * FROM table_a a JOIN table_b b ON a.seq = b.seq;
優點:合併關係**確定、可重現、可驗證**。缺點:需 DDL 修改表、更新耗時、佔用序列值。
| 指標 | ROWNUM 合併 | 序列合併 |
|---|---|---|
| 建立合併鍵時間 | 0 秒 (查詢時產生) | ~10 分鐘 (兩表更新) |
| 合併查詢耗時 | 5.6 秒 | 24.4 秒 |
| 執行計畫 | HASH JOIN + VIEW + COUNT | 相同 |
| 結果正確性 | **不可預測、極大機率錯誤** | **完全正確、可重現** |
| 緩存影響 | 第二次執行極快 (資料在記憶體) | 同樣受惠緩存 |
| 場景 | 建議做法 |
|---|---|
| 資料量小 (< 10 萬)、一次性臨時分析、不在意配對關係 | ROWNUM 可接受(但需加 ORDER BY PK 穩定順序) |
| 正式上線、需可重現、資料量大、有業務邏輯關聯 | **必須用實體合併鍵 (序列、UUID、業務流水號)** |
| 定期 ETL、可預先在來源系統打上合併鍵 | 上游產生 MERGE_KEY,下游直接 JOIN |
ORA_HASH(pk, 999) 將兩表分 1000 桶,桶內再 ROWNUM 配對,減少跨桶錯配。NEXTVAL 產生鍵,避免落地更新。ROWNUM 看似捷徑,實則埋下資料錯配的地雷。投入少量時間建立實體合併鍵,換來的是可驗證、可審計、可重跑的資料管線——這才是專業資料工程的態度。