Oracle 12c 前無 GENERATED AS IDENTITY 語法,傳統做法是 Sequence(序列)+ Trigger(觸發器) 組合。即使 12c+ 支援 Identity,Sequence+Trigger 仍因靈活性(跨表共用序列、自定義快取、手動控制)被廣泛使用。本文提供生產級完整範例,涵蓋建表、建序列、建觸發器、效能調優、常見坑點。
CREATE TABLE users (
id NUMBER(18) NOT NULL,
username VARCHAR2(50) NOT NULL,
password VARCHAR2(100) NOT NULL,
email VARCHAR2(100),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP NOT NULL,
CONSTRAINT pk_users PRIMARY KEY (id)
) TABLESPACE users_data
PCTFREE 10
STORAGE (INITIAL 64M NEXT 64M MAXEXTENTS UNLIMITED);
CREATE SEQUENCE seq_users_id
START WITH 1
INCREMENT BY 1
NOCACHE -- 或 CACHE 1000(高併發建議)
NOMAXVALUE
NOCYCLE
NOORDER; -- RAC 環境建議 ORDER 保證全域有序
| 參數 | 推薦值 | 理由 |
|---|---|---|
| CACHE | 1000~10000 | 高併發減少 Sequence Cache 鎖競爭;單機小系統可 NOCACHE 避免跳號 |
| ORDER/NOORDER | RAC 必 ORDER | RAC 下 NOORDER 可能導致跨節點號碼倒退,應用若依賴單調遞增必須 ORDER |
| MAXVALUE | NOMAXVALUE | NUMBER(18) 上限 10^18,業務極難耗盡 |
| 現象 | 原因 | 解法 |
|---|---|---|
| ID 跳號(非連續) | Sequence Cache 失效(實例重啟、Age Out)、Rollback、手動指定 ID | 業務接受跳號;若需連續需應用層管理 |
| ORA-00001 PK Violation | 手動 INSERT 指定 ID 與 Sequence 產生值衝突 | Trigger 加 WHEN (NEW.id IS NULL);遷移資料時先調整 Sequence NEXTVAL > MAX(ID) |
| RAC 下 ID 倒退 | NOORDER 導致各節點獨立 Cache | 建序列加 ORDER;或接受最終一致性 |
| Trigger 失效 | DDL 變更導致 Trigger INVALID | 部署腳本最後加 ALTER TRIGGER ... COMPILE;監控 USER_TRIGGERS.STATUS |
-- 遷移歷史資料後,將 Sequence 推進至 MAX(ID) 以上
SELECT 'ALTER SEQUENCE seq_users_id INCREMENT BY ' || (max_id - curr_val + 1000) || ';'
FROM (SELECT MAX(id) max_id FROM users),
(SELECT seq_users_id.CURRVAL curr_val FROM dual);
-- 執行上述動態 SQL,再改回 INCREMENT BY 1
ALTER SEQUENCE seq_users_id INCREMENT BY 1;
Sequence + Trigger 是 Oracle 自增主鍵的經典模式,關鍵在於:CACHE 參數對效能的決定性影響、WHEN 子句對遷移相容性的支援、RAC 環境下 ORDER/NOORDER 的架構決策。12c+ 專案可優先評估 Identity Column,但掌握傳統模式調優細節,對維護既有系統、跨版本遷移仍具核心價值。