sys_guid() 返回 raw(16) 类型,非 rfc 4122 标准 uuid 字符串;需用 rawtohex() 转为 32 位十六进制,再按 8-4-4-4-12 位切分拼接,并确保仅调用一次 sys_guid() 避免值分裂。

SYS_GUID() 能生成全局唯一值,但不是标准 UUID 字符串——直接用它当主键传给 Java 或前端会解析失败。
为什么 SYS_GUID() 返回的不是标准 UUID?
它返回的是 RAW(16) 类型,比如 A8F662B86E7413FEE040970A437C6BD7。这不是 RFC 4122 要求的 8-4-4-4-12 格式字符串,也没有连字符,大小写也不统一。下游系统(如 java.util.UUID)会拒绝解析 raw 值;TO_CHAR(SYS_GUID()) 更危险——它按数据库字符集映射字节,可能产出乱码或非法字符。
正确转换:先 RAWTOHEX(),再切分拼接
必须只调用一次 SYS_GUID(),否则每多调用一次就生成一个新值,导致 UUID 四分五裂。安全做法是:
- 用
RAWTOHEX(SYS_GUID())得到 32 位大写十六进制字符串(如'A8F662B86E7413FEE040970A437C6BD7') - 用
SUBSTR按位置提取并拼接:SUBSTR(str,1,8)||'-'||SUBSTR(str,9,4)||'-'||SUBSTR(str,13,4)||'-'||SUBSTR(str,17,4)||'-'||SUBSTR(str,21,12) - 若需小写,整个结果套
LOWER(),别对SYS_GUID()直接LOWER
错误示例(生成 5 个不同 GUID):
SELECT SUBSTR(RAWTOHEX(SYS_GUID()),1,8)||'-'||SUBSTR(RAWTOHEX(SYS_GUID()),9,4)... FROM DUAL;
封装成函数才真正可用
每次 SQL 查询都手写切分太容易出错,也难复用。推荐创建一个带变量缓存的函数:
CREATE OR REPLACE FUNCTION get_uuid RETURN VARCHAR2 IS
v_raw RAW(16) := SYS_GUID();
v_hex VARCHAR2(32) := RAWTOHEX(v_raw);
BEGIN
RETURN LOWER(SUBSTR(v_hex,1,8) || '-' ||
SUBSTR(v_hex,9,4) || '-' ||
SUBSTR(v_hex,13,4) || '-' ||
SUBSTR(v_hex,17,4) || '-' ||
SUBSTR(v_hex,21,12));
END;
调用:SELECT get_uuid() FROM DUAL;
注意:函数体里 v_raw 只赋值一次,确保所有 SUBSTR 操作基于同一个原始值——这是避免“UUID 错位”的关键,也是最容易被忽略的执行细节。











