SQL插入数据时怎样动态生成全局唯一标识符

作者:袖梨 2026-07-11
数据库原生UUID生成最稳,但需按数据库选函数:MySQL用UUID()配CHAR(36),SQL Server用NEWID()或NEWSEQUENTIALID()配UNIQUEIDENTIFIER,PostgreSQL优先用pgcrypto的gen_random_uuid()配UUID,跨库须抽象方言或应用层生成。

直接用数据库原生函数最稳,别自己拼字符串或依赖应用层生成——除非你明确需要跨库一致性或特殊格式。

MySQL 8.0+ 用 UUID(),但字段类型和长度得配对

UUID() 返回的是 36 字符的带连字符字符串(如 550e8400-e29b-41d4-a716-446655440000),不是二进制。如果建表时用了 CHAR(36)VARCHAR(36),能存下;但用 CHAR(32) 会截断连字符,导致数据损坏。

  • 建表推荐写法:id CHAR(36) DEFAULT UUID() PRIMARY KEY
  • 插入时不指定值即可触发默认:INSERT INTO users (name) VALUES ('Alice')
  • 别在 WHERE 条件里用 UUID() 做等值匹配——它每次调用都不同,WHERE id = UUID() 永远不成立
  • 性能注意:UUID 无序,作为聚簇主键会导致频繁页分裂,高并发写入时建议搭配 INNODBROW_FORMAT=COMPRESSED 或改用自增 ID + 单独加唯一索引

SQL Server 必须用 NEWID()NEWSEQUENTIALID(),不能混用

NEWID() 是随机 GUID,NEWSEQUENTIALID() 是递增 GUID,二者行为差异极大,且 NEWSEQUENTIALID() 只能用于列默认值,不能出现在 INSERT 或 SELECT 表达式中。

  • 建表时设默认值:id UNIQUEIDENTIFIER DEFAULT NEWID() PRIMARY KEY
  • 想减少索引碎片?换 DEFAULT NEWSEQUENTIALID(),但注意它不能在 INSERT ... VALUES (NEWSEQUENTIALID(), ...) 中直接调用,会报错 Invalid use of 'NEWSEQUENTIALID'
  • 别把 UNIQUEIDENTIFIER 字段设成 NOT NULL 却不设默认值或不显式插入——否则插入失败
  • 如果要用短 ID(如 UID12345678),得靠计算字段或触发器,但 NEWID() 本身不支持截取后设默认值(函数有副作用,不能在列定义里用)

PostgreSQL 要先装扩展,gen_random_uuid() 才可用

PostgreSQL 默认不提供 UUID 生成函数。uuid-ossp 需要超级用户权限启用,CI 环境常卡住;pgcrypto 更轻量,普通用户也能装,推荐优先用它。

  • 启用扩展:CREATE EXTENSION IF NOT EXISTS "pgcrypto"
  • 建表:id UUID DEFAULT gen_random_uuid() PRIMARY KEY
  • 插入:INSERT INTO users (name) VALUES ('Bob'),自动填充
  • 别误写成 uuid_generate_v4() —— 它属于 uuid-ossp,没装扩展会报错 function uuid_generate_v4() does not exist
  • gen_random_uuid() 生成的是 RFC 4122 v4 UUID,无序;如需时间有序,得用第三方扩展如 pg_uuidv7,不在原生范围内

真正容易被忽略的点是:跨数据库迁移脚本时,UUID()NEWID()gen_random_uuid() 三者语法不兼容,硬编码函数名等于埋雷。如果项目要支持多库,要么统一用应用层生成(比如 Python 的 uuid.uuid4().hex),要么抽象出方言适配层,别指望一条 SQL 走天下。

相关文章

精彩推荐