在 Oracle 資料庫中,產生 UUID 的標準方法是 SYS_GUID() 函式,它會回傳一個由主機識別碼和時間戳記組成的 16 位元組 RAW 值。若要將該 RAW 值轉換為常見的 8-4-4-4-12 十六進位字串,可以用 RAWTOHEX() 和 SUBSTR() 包裹它來插入連字號,或如果你的欄位接受 RAW,也可以直接儲存。Oracle 23c 引入了原生 UUID 資料型別和 random_uuid() 函式,它會回傳符合 RFC 4122 版面的正確格式化 36 字串帶連字號。Oracle 的內建產生器都無法在嚴格意義上產生標記為第 4 版的 UUID,因為 SYS_GUID 僅將自己標示為全域唯一識別碼,而非有版本的 UUID,而 random_uuid 是較新的便利函式,無法保證版本和變體位元組。對於應用程式層的 ID、測試 fixtures,或任何在資料庫外建立的識別碼,你可以在瀏覽器中使用 UUID Generator 工具來產生 RFC 4122 第 4 版 UUID,然後直接貼到 SQL、應用程式碼或種子腳本中。

Oracle 內建 UUID 函式一覽
Oracle 在資料庫中提供三種不同的 UUID 產生機制,而且它們並非一次全部推出。SYS_GUID() 已經存在數十年,在所有支援的版本中都能使用。原生 UUID 欄位型別和 random_uuid() 函式則隨著 Oracle Database 23c 一起推出,資料庫終於趕上了開發人員多年來在其他地方使用的儲存和格式化慣例。每個函式回傳的資料型別不同,使用的文字版面也不同,所以選擇哪一個取決於你的 Oracle 版本,以及系統中其他部分打算如何使用該值。
| 函式 | 自哪個版本起可用 | 回傳型別 | 預設文字格式 | 版本欄位 |
|---|---|---|---|---|
| SYS_GUID() | 歷史悠久 (pre-12c) | RAW(16) | 32 個十六進位字元,無連字號 | 未標示 |
| UUID 欄位型別 | Oracle 23c | UUID (原生 128 位元) | 轉為字串時帶連字號 | 未嚴格符合 RFC 4122 |
| random_uuid() | Oracle 23c | VARCHAR2(36) | 8-4-4-4-12 帶連字號字串 | RFC 4122 風格輸出 |
在 SQL 查詢中使用 SYS_GUID()
最常見的 Oracle 模式是在 INSERT 或 DEFAULT 子句中直接呼叫 SYS_GUID(),然後用 RAWTOHEX() 轉換 RAW 結果。單純呼叫 SYS_GUID() 會回傳一個 16 位元組的二進位值,SQL*Plus 會將其以原始位元組印出,所以你幾乎總是會在顯示前先將其包裹:
SELECT RAWTOHEX(SYS_GUID()) AS uuid FROM DUAL;
它會回傳類似 7B8F4D2C9E1A4F6B8C0D3E5F7A9B1C2D 的結果,一個 32 字元、無分隔符的十六進位字串。如果你的應用程式預期使用 RFC 4122 和大多數其他資料庫所用的帶連字號格式,你可以用 SUBSTR 和串接來重新格式化:
SELECT LOWER(SUBSTR(hex,1,8) || '-' || SUBSTR(hex,9,4) || '-' || SUBSTR(hex,13,4) || '-' || SUBSTR(hex,17,4) || '-' || SUBSTR(hex,21,12)) AS uuid FROM (SELECT RAWTOHEX(SYS_GUID()) AS hex FROM DUAL);
許多團隊完全略過連字號,將 32 字元十六進位格式直接儲存在 CHAR(32) 欄位中。這樣可以讓索引保持精簡,避免在應用程式層進行字串處理,但代價是與預期使用帶連字號 UUID 的系統失去相容性。SYS_GUID() 的設計保證機器之間絕不衝突,但它不像 RFC 4122 v4 UUID 那樣是均勻隨機的值,這就是為什麼它不公開版本數字。
Oracle 23c 原生 UUID 欄位型別與 random_uuid()
Oracle Database 23c 引入了真正的 UUID 資料型別,因此你無需在 RAW、VARCHAR2 或 CHAR 之間抉擇就能宣告一個欄位。該欄位接受以帶連字號格式寫入的值,並在內部以 128 位元二進位儲存,反映 PostgreSQL 多年來處理 UUID 的方式。你可以依賴資料庫使用 DEFAULT 來填入欄位,這會觸發與 random_uuid() 函式相同的產生常式:
CREATE TABLE orders (id UUID DEFAULT random_uuid() PRIMARY KEY, customer_id UUID, created_at TIMESTAMP);
random_uuid() 函式回傳一個 VARCHAR2(36) 字串,版面為 8-4-4-4-12,十六進位數字的選擇會符合 RFC 4122 識別碼的外觀。Oracle 文件將其描述為「回傳一個隨機產生的 UUID,作為 36 個字元的字串」,所以對於欄位預設值和臨時的 SELECT 陳述式來說,它是 23c 及以後版本中最方便的選項。在更早的版本中,實際的選擇仍是 SYS_GUID() 加上你自己的格式化,或者完全跳過資料庫。
Oracle 輸出與 RFC 4122 的格式差異
在 Oracle 中產生 UUID 時最大的陷阱是,這三個選項都無法嚴格產生 RFC 4122 第 4 版值。SYS_GUID 由系統資訊建構而成,並未按照 RFC 4122 保留的版本和變體位元組進行結構化,而 random_uuid() 雖然輸出形狀正確的帶連字號字串,但無法保證第 13 個十六進位數字是 4,第 17 個是 8、9、a 或 b 其中之一。實際效果是,Oracle 產生的識別碼幾乎總是唯一的,大多數跨系統的程式碼也會將其視為 UUID,但嚴格按照 RFC 4122 檢查版本和變體位元組的驗證器可能會拒絕它。
| 面向 | SYS_GUID() | random_uuid() / UUID 欄位 | RFC 4122 v4 (UUID Generator) |
|---|---|---|---|
| 長度 | 32 個十六進位字元 | 36 個字元含連字號 | 36 個字元含連字號 |
| 隨機性來源 | 系統衍生的位元 | 資料庫 RNG | 瀏覽器 CSPRNG (Web Crypto) |
| 第 13 個十六進位數字 | 不固定 | 不固定 | 永遠是 4 |
| 第 17 個十六進位數字 | 不固定 | 不固定 | 8、9、a 或 b |
| 可用位元 | 122 (結構化) | 122 | 122 純隨機 |
這就是為什麼許多需要嚴格合規識別碼的團隊將產生作業移到資料庫外部。在瀏覽器中由 RFC 4122 v4 UUID 產生器產生的值,可以保證版本和變體位元組落在正確位置,其中 122 個位元由平台 CSPRNG 提供,真正隨機。
使用 UUID Generator 在資料庫外產生 UUID
當你需要一個嚴格符合 RFC 4122 的 UUID,或是在資料庫還未介入之前就需要 ID 時,最快的途徑是使用瀏覽器型產生器。UUID Generator 在本機使用 Web Crypto API 的 getRandomValues 來產生一個或多個第 4 版 UUID 作為隨機位元,因此每個值在統計上獨立且無法猜測。若要為 Oracle 專案產生識別碼:
- 開啟 UUID Generator,輸入你需要的數量,一次最多 100 個。
- 如果你的 Oracle 欄位儲存 CHAR(32) 十六進位或偏好不同大小寫,可以切換為大寫或移除連字號。
- 點擊 Generate,然後複製單一 UUID,或使用 Copy all 一次取得所有值。
- 將結果貼到你的 INSERT 陳述式、PL/SQL 區塊、種子檔案或應用程式碼中。
每個 UUID 都在你自己的瀏覽器分頁中產生,該工具絕不會將值傳送至伺服器,因此無論是正式環境的識別碼或內部秘密都安全使用。由於隨機位元來自 CSPRNG,這些值的抗碰撞性足以視為全域唯一,無需與資料庫協調,並能通過任何指向它們的 RFC 4122 v4 驗證器。
為你的專案挑選合適的 UUID 來源
若你想在資料庫端使用預設值,而且滿意於 32 字元十六進位字串或自訂的帶連字號格式,可在 Oracle 12c 到 19c 選擇 SYS_GUID()。在 23c 及更新版本中,為了最簡潔的儲存模型和最簡單的應用程式碼,建議使用原生 UUID 欄位型別搭配 random_uuid() 預設值。當消費者位於 Oracle 之外、該值必須滿足嚴格的 RFC 4122 驗證器,或你正在植入測試資料、產生 API 請求 ID,或將識別碼寫入用戶端程式碼時,請使用 UUID Generator。這兩種做法並不互斥:許多團隊在 Oracle 內部使用 random_uuid() 作為主鍵,並對所有跨越資料庫邊界的項目使用瀏覽器產生器。
如果你也使用 JavaScript 產生識別碼,請參閱 how to generate UUIDs in JavaScript 的配套指南,了解瀏覽器端和 Node 端的對應模式。
如果你正在權衡各種選擇,VS Code Keyboard Shortcuts: Defaults Compared by Platform 對此有詳細介紹。