MySQL用UUID()、PostgreSQL用gen_random_uuid()、SQL Server用NEWID()、Oracle用SYS_GUID()可在UPDATE中生成唯一标识,但需注意字段类型、索引影响及扩展启用等限制。

UPDATE 时用 UUID() 生成唯一标识
MySQL 中直接在 UPDATE 语句里调用 UUID() 是可行的,它每次执行都返回一个新值,适合给未设置主键或需要唯一追踪 ID 的记录补全标识。
常见错误是误以为 UUID() 可以“按顺序”生成——它本质是随机字符串,不保证时间/插入顺序,也不适合作为索引主键(会导致页分裂)。
- 仅对
NULL或空字符串字段更新:UPDATE users SET uuid = UUID() WHERE uuid IS NULL; - 避免在大表上无条件执行:没加
WHERE会全表重写,锁表时间长,且 UUID 值不可预测,后续难追溯原始顺序 - 注意字符集和字段长度:
CHAR(36)是安全选择;若用UUID_SHORT(),需确保 server_id 已配置且非 0,否则可能重复
PostgreSQL 中用 gen_random_uuid() 替代 uuid_generate_v4()
PostgreSQL 默认不内置 UUID 函数,必须先启用 pgcrypto 或 uuid-ossp 扩展。现在推荐用 pgcrypto 的 gen_random_uuid(),它不依赖序列对象、无锁、性能更好。
容易踩的坑是扩展没提前加载——执行 UPDATE 时会报错 function gen_random_uuid() does not exist。
- 启用扩展(只需一次):
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; - 更新语句示例:
UPDATE logs SET id = gen_random_uuid() WHERE id IS NULL; - 不要混用
uuid_generate_v4():它依赖uuid-ossp,该扩展在某些云托管 PG(如 AWS RDS 默认配置)中被禁用,且函数调用开销略高
SQL Server 用 NEWID() 而不是 NEWSEQUENTIALID() 做动态填充
NEWID() 是最直接的选择,每次调用生成新 GUID;NEWSEQUENTIALID() 只能在默认约束中使用,不能在 UPDATE 语句里直接调用——这是硬性限制,尝试会报错 Cannot use NEWSEQUENTIALID() here。
如果字段是 UNIQUEIDENTIFIER 类型,且已有部分记录为空,就只能靠 NEWID() 补全。
- 安全写法:
UPDATE orders SET guid = NEWID() WHERE guid IS NULL; - 别在
WHERE条件里依赖NEWID():比如WHERE NEWID() > '0'会导致每行重新计算,结果不可控 - 注意索引碎片:大量用
NEWID()更新聚集索引列,会显著降低插入性能,建议这类字段不设为聚集索引
Oracle 没有内置 UUID 函数,得靠 SYS_GUID() 或自定义逻辑
Oracle 的 SYS_GUID() 返回 RAW(16),不是标准 UUID 字符串格式(带连字符)。如果业务要求 8-4-4-4-12 格式,必须手动转换,且不能在纯 SQL UPDATE 中完成——因为 PL/SQL 函数无法直接用于 SET 子句的表达式上下文(除非封装成 SQL 可调用函数)。
最简方案是接受 RAW,或用应用层生成后再 UPDATE;硬要在 SQL 层做,就得先建函数:
CREATE OR REPLACE FUNCTION uuid_to_char(p_guid IN RAW) RETURN VARCHAR2 IS BEGIN RETURN RAWTOHEX(p_guid); END;
但这样仍得不到标准 UUID 格式,真正合规的转换(加连字符)需额外 SUBSTR 拼接,在 UPDATE 中极难维护。
- 务实做法:
UPDATE products SET guid = SYS_GUID() WHERE guid IS NULL;,应用层负责展示时格式化 - 别试图在 UPDATE 里用
DBMS_RANDOM.STRING()拼 UUID:既不标准,也不保证唯一性 - 注意
SYS_GUID()在 RAC 环境下仍唯一,但不同节点生成的值无序,不适合做范围扫描


















